pku 2411 Mondriaan's Dream(状态压缩DP)

状态压缩DP。

一行一行的处理,每行对应一个状态。每一行中,每个位置有2种状态,状态0表示该位置恰好填满,状态1表示该位置对应的下一行也被填上了。如果状态next可以由状态now转换来,则DP[i+1][next]+=DP[i][now]。

对于一个m*n的矩形,有m行,每行有2^n个状态,于是总的效率为O(m*2^n*2^n)。

大概流程就是这个样子,细节见代码。

#include <algorithm> #include <iostream> using namespace std; int m,n,end; __int64 DP[13][1<<11]; bool OK(int now,int next) { int temp=1<<n; now=now|temp; int p,q; for(int i=0;i<n;i++) { p=now&1; q=next&1; if(p==1) { if(q==1) return false; } else { if(q==0) { i++; now=now>>1; next=next>>1; p=now&1; q=next&1; if(p==1||q==1) return false; } } now=now>>1; next=next>>1; } return true; } int main() { while(scanf("%d%d",&m,&n)) { if(m==0&&n==0) break; if((m*n)%2) { printf("0/n"); continue; } if(n>m) swap(m,n); end=1<<n; memset(DP,0,sizeof(DP)); DP[0][0]=1; for(int i=0;i<m;i++) { for(int j=0;j<end;j++) { for(int k=0;k<end;k++) { if(OK(j,k)) DP[i+1][k]+=DP[i][j]; } } } printf("%I64d/n",DP[m][0]); } return 0; }

你可能感兴趣的:(pku 2411 Mondriaan's Dream(状态压缩DP))