玉米田Corn Fields
此题和互不侵犯状压DP的做法类似
f[i][j]表示前i行,第i行种植(1)/不种植(0)构成的二进制数为j时的方案数
首先我们可以预处理出所有一行中没有两个相邻的1的二进制数
然后进行暴力的DP
1 #include<cstdio> 2 #define mod 100000000 3 #define N 13 4 #define M 4100 5 int n,m,f[N][M],a[N]; 6 int s[378],cnt,ans; 7 inline int read(){ 8 char c=getchar(); 9 while(c!='0'&&c!='1') c=getchar(); 10 return c-'0'; 11 } 12 int main() 13 { 14 scanf("%d%d",&n,&m); 15 for(int i=1;i<=n;i++){ 16 int x=0; 17 for(int j=m-1;j>=0;j--) 18 x+=read()*(1<<j); //处理出该行对应的二进制数 19 a[i]=x; 20 } 21 for(int i=0;i<(1<<m);i++) 22 if((i&(i<<1))==0) //若没有两个相邻的1 23 s[++cnt]=i; //存在数组中 24 for(int i=1;i<=cnt;i++) //初始化第一行边界 25 if((s[i]&a[1])==s[i]) 26 f[1][s[i]]=1; 27 for(int i=2;i<=n;i++) 28 for(int j=1;j<=cnt;j++) 29 if((s[j]&a[i])==s[j]) //若s[j]中的1碰上a[i]中的0,就成了0 30 for(int k=1;k<=cnt;k++) 31 if((s[k]&s[j])==0) 32 f[i][s[j]]=(f[i][s[j]]+f[i-1][s[k]])%mod; 33 for(int i=1;i<=cnt;i++) 34 ans=(ans+f[n][s[i]])%mod; 35 printf("%d ",ans); 36 return 0; 37 }