POJ 2411 Mondriaan's Dream 状态压缩dp

来源:互联网 发布:数据库系统工程师真题 编辑:程序博客网 时间:2024/05/16 15:55

http://poj.org/problem?id=2411

题意:给定一个N*M的矩形区域,用1*2的小矩形将其填满,问一共有多少种填法。1<=N,M<=11

思路:状态压缩dp 。用dp[i][j]表示将前i-1行正好完全填满,i行状态为j时的种数,状态转移方程为:dp[i][j] = sum{dp[i-1][pre]},其中pre状态可以转化为j状态。在已知pre求j就的时候,我们可以用一次dfs来搜索出所有可以从pre转化的状态。

代码:

/*状态压缩dp */#include<stdio.h>#include<string.h>int N , M ;long long dp[15][1<<11] ;void dfs(int row,int pos , int pre, int now){if(pos == M+1){if(dp[row][now] == -1){dp[row][now] = dp[row-1][pre] ;}else{dp[row][now] += dp[row-1][pre] ;}return ;}if( (pre&(1<<(pos-1))) != 0)dfs(row,pos+1,pre,now<<1);else{dfs(row,pos+1,pre,(now<<1)+1);if(pos+1<=M && (pre&(1<<pos)) ==0){dfs(row,pos+2,pre,now<<2) ;}}} void DP(){int MA = (1 << M) - 1 ;memset(dp , -1 ,sizeof(dp));dp[0][MA] = 1  ;for(int i=1;i<=N+1;i++){for(int j=0;j<=MA;j++){if(dp[i-1][j] == -1)continue ;dfs(i,1,j,0);}}if(dp[N+1][0] == -1){printf("0\n");}elseprintf("%lld\n",dp[N+1][0]);} int main(){while(scanf("%d %d",&N,&M) == 2){if(0==N && M==0)break ;if(N * M % 2 != 0){printf("0\n");continue ;}DP();}return 0 ;}