poj 3254 状态压缩DP
思路:把每行的数当做是一个二进制串,0不变,1变或不变,找出所有的合法二进制形式表示的整数,即相邻不同为1,那么第i-1行与第i行的状态转移方程为dp[i][j]+=dp[i-1][k];
这个方程得前提条件是num[i][j]&num[i-1][k]==0,也就是他们表示的二进制形式相与为0,那么就不存在相邻为1的情况。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define Maxn 13 #define inf 0x7fffffff using namespace std; __int64 dp[Maxn][1<<Maxn]; int num[13][1<<Maxn],cnt1,cnt2,graphic[Maxn][Maxn],co,n,m; void dfs(int u,int j) { int i; if(j==m) { int sum=0; for(i=m;i>=1;i--) sum+=graphic[u][i]*(1<<(m-i)); if(graphic[u][j]==1) { if(graphic[u][j-1]==0) { num[u][++cnt2]=sum; num[u][++cnt2]=sum-1; } else { num[u][++cnt2]=sum-1; } } else num[u][++cnt2]=sum; return ; } if(graphic[u][j]==1) { if(graphic[u][j-1]==0) { dfs(u,j+1); graphic[u][j]=0; dfs(u,j+1); graphic[u][j]=1; } else { graphic[u][j]=0; dfs(u,j+1); graphic[u][j]=1; } } else dfs(u,j+1); } int main() { int i,j,k; while(scanf("%d%d",&n,&m)!=EOF) { memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&graphic[i][j]); for(i=1;i<=n;i++) graphic[i][0]=0; cnt2=0; dfs(1,1); for(i=1;i<=cnt2;i++) dp[1][i]=1; for(i=2;i<=n;i++) { cnt1=cnt2;cnt2=0; dfs(i,1); for(j=1;j<=cnt2;j++) { for(k=1;k<=cnt1;k++) { if(!(num[i-1][k]&num[i][j])) dp[i][j]+=dp[i-1][k],dp[i][j]%=100000000; } } } __int64 ans=0; for(i=1;i<=cnt2;i++) ans+=dp[n][i]; printf("%I64d\n",ans%100000000); } return 0; }