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的主要内容,如果未能解决你的问题,请参考以下文章