[USACO06NOV]玉米田
题目链接:https://www.luogu.org/problemnew/show/P1879
第一次自己写状压DP纪念。
题意简述:m*n的草地。其中有些草地不能种草,而种草的两个方格不能四相邻。
求有多少种草地的规划方法,答案对100000000取模。
1<=n,m<=12
说得啰嗦一点吧。。。
把每一行的方案看成一个二进制数,f[i][j]表示第i行方案为j的方案数。
提前预处理出同一行内无相邻种草方格的方案,以及每一行内,所有能种草的方格都种草代表的二进制数。
枚举上一行可能出现的情况,如果两行之间没有相邻种草方块。(j&l==0)且没有种到不能种草的方块上(j&g[i]==j),那么就能转移。
#include<cstdio> const int c=100000000; void read(int &y) { y=0;char x=getchar(); while(x<'0'||x>'9') x=getchar(); while(x>='0'&&x<='9') { y=y*10+x-'0'; x=getchar(); } } int m,n,k,ans; int a[15][15],g[15]; int b[5005],f[15][5005]; int main() { read(m);read(n); int k=(1<<n); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { read(a[i][j]); g[i]<<=1; g[i]+=a[i][j]; } } for(int i=0;i<k;i++) { if((i&(i<<1))||i&(i>>1)) continue; b[i]=1; } f[0][0]=1; for(int i=1;i<=m;i++) { for(int j=0;j<k;j++) { if((j&g[i])!=j||b[j]==0) continue; for(int l=0;l<k;l++) { if((j&l)==0&&b[l]) { f[i][j]+=f[i-1][l]; f[i][j]%=c; } } } } for(int i=0;i<k;i++) ans+=f[m][i]; printf("%d",ans%c); return 0; }