bzoj 2331: [SCOI2011]地板 插头dp

Posted SD_le

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2331: [SCOI2011]地板 插头dp相关的知识,希望对你有一定的参考价值。

  用四进制表示状态。

  用hash表把一个四进制数映射到一个小数上。

  这样就可以memset了。

  转移的时候分类讨论一下,特判下边界情况。

  

  1 #include<iostream>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #define bq 1<<bit[j]
  6 #define bp 1<<bit[j-1]
  7 using namespace std;
  8 int n,m;
  9 int map[105][105],bi[105][105];
 10 char s[105];
 11 const int maxn=200010;
 12 int f[2][maxn],tot[2],hash[2][maxn],head[maxn],ver[maxn],nxt[maxn],bit[110];
 13 int num,pre,now;
 14 const int mod = 20110520;
 15 void add(int s,int d)
 16 {
 17     int x=s%50000;
 18     for(int i=head[x];i;i=nxt[i])
 19     {
 20         if(hash[now][ver[i]]==s)
 21         {
 22             f[now][ver[i]]=(f[now][ver[i]]+d)%mod;
 23             return ;
 24         }
 25     }
 26     tot[now]++;
 27     hash[now][tot[now]]=s;
 28     f[now][tot[now]]=d;
 29     num++;ver[num]=tot[now];nxt[num]=head[x];head[x]=num;
 30     return ;
 31 }
 32 int main()
 33 {
 34     for(int i=1;i<=100;i++)bit[i]=i*2;
 35     scanf("%d%d",&n,&m);
 36     for(int i=1;i<=n;i++)
 37     {
 38         scanf("%s",s);
 39         for(int j=1;j<=m;j++)
 40         {
 41             if(s[j-1]==*)map[i][j]=0;
 42             else map[i][j]=1;
 43         }
 44     }
 45     if(n<m)
 46     {
 47         for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)bi[j][i]=map[i][j]; 
 48         memset(map,0,sizeof(map));
 49         for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)map[j][i]=bi[j][i];
 50         swap(n,m);
 51     }
 52     now=1;pre=0;tot[now]=1;hash[now][1]=0;f[now][1]=1;
 53     for(int i=1;i<=n;i++)
 54     {
 55         for(int j=1;j<=tot[now];j++)hash[now][j]<<=2;
 56         for(int j=1;j<=m;j++)
 57         {
 58             now^=1;pre^=1;
 59                memset(head,0,sizeof(head));
 60                memset(f[now],0,sizeof(f[now]));
 61             tot[now]=0;num=0;
 62             for(int k=1;k<=tot[pre];k++)
 63             {
 64                 int s=hash[pre][k],num=f[pre][k];
 65                 if(!num)continue;
 66                 int p=(s/(bp))&3,q=(s/(bq))&3;
 67                 if(!map[i][j])
 68                 {
 69                     if(!p&&!q)add(s,num);
 70                 }
 71                 else if(!p&&!q)
 72                 {
 73                     add(s+(bp),num);
 74                     if(j<m)add(s|(bq),num),add(s|(bp+1)|(bq+1),num);
 75                 }
 76                 else if(!p)
 77                 {
 78                     if(q==1)
 79                     {
 80                         s^=(bq);
 81                         add(s|(bp),num);
 82                         if(j<m)add(s|(bq+1),num);
 83                     }
 84                     else
 85                     {
 86                         s^=(bq+1);
 87                         add(s|(bp+1),num);
 88                         add(s,num);
 89                     }
 90                 }
 91                 else if(!q)
 92                 {
 93                     if(p==1)
 94                     {
 95                         s^=(bp);
 96                         add(s|(bp+1),num);
 97                         if(j<m)add(s|(bq),num);
 98                     }
 99                     else
100                     {
101                         s^=(bp+1);
102                         if(j<m)add(s|(bq+1),num);
103                         add(s,num);
104                     }
105                 }
106                 else if(p==1&&q==1)
107                 {
108                     add(s^(bq)^(bp),num);
109                 }
110             }   
111         }
112     }
113     int ans=0;
114     for(int i=head[0];i;i=nxt[i])
115     {
116         if(hash[now][ver[i]]==0)ans=f[now][ver[i]];
117     }
118     printf("%d\n",ans);
119     return 0;
120 }

 

以上是关于bzoj 2331: [SCOI2011]地板 插头dp的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ2331:[SCOI2011]地板——题解

bzoj2331 [SCOI2011]地板

BZOJ2331: [SCOI2011]地板

bzoj 2331: [SCOI2011]地板 插头dp

BZOJ2331: [SCOI2011]地板 插头DP

2331: [SCOI2011]地板 插头DP