题意:
给一块n*m的田地,1代表肥沃,0代表贫瘠。
现在要求在肥沃的土地上种草,要求任何两个草都不能相邻。
问一共有多少种种草的方法。
种0棵草也是其中的一种方法。
n和m都不大于12.
思路:
状态压缩DP,dp[i][j]代表在第i行状态j一共有多少种可能的种植方法。
j是二进制转化而来的状态,0代表不种草,1代表种草。
dp[i]只受到两个限制,即dp[i-1]的某种状态,和当前土地的贫瘠状况。
只要保证&操作之后重复的为0就可以了
最后输出sum(dp[n][1...w])(w代表一共有w种可行的状态)
#include<stdio.h> int pho[15][15]; int biao[15]; int dp[15][1<<13]; int may[1<<13]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&pho[i][j]); if(pho[i][j]) { pho[i][j]=0; } else { pho[i][j]=1; } } } for(int i=1;i<=n;i++) { int tmp=pho[i][1]; for(int j=2;j<=m;j++) { tmp=tmp<<1; tmp+=pho[i][j]; } biao[i]=tmp; } int num=1; for(int s=0;s<(1<<m);s++) { if((s&(s<<1))==0) { may[num++]=s; } } for(int i=1;i<num;i++) { if((may[i]&biao[1])==0) { dp[1][i]=1; } } for(int i=2;i<=n;i++) { for(int j=1;j<num;j++) { for(int k=1;k<num;k++) { if((may[k]&may[j])||(may[j]&biao[i])) continue; dp[i][j]+=dp[i-1][k]; dp[i][j]%=1000000000; } } } int ans=0; for(int i=1;i<num;i++) { ans+=dp[n][i]; ans%=1000000000; } printf("%d ",ans); return 0; }