POJ 2411 Mondriaan's Dream
今天感觉很不错啊,一上来就A了这道题。这可是卡了四天的啊~~
题目大意:
给出n×m的矩形,问用1×2的矩形完全覆盖有多少种方案。
解题思路:
状态压缩DP和状态压缩记忆化搜索都行:前者是从第一行的状态开始向下推到终止状态;后者是从终止状态开始搜索,并保存中间状态。
我用的是状态压缩DP写的,可以提前与处理一下状态与状态之间的关系。
下面是代码:
#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> #include <stdlib.h> using namespace std; int min(int a,int b) { if(a>b)a=b; return a; } int max(int a,int b) { if(a<b)a=b; return a; } long long dp[12][1<<11]; int w,h; bool vis[1<<11][1<<11]; bool judge(int a,int b) { int num=1<<h,cnt=0; for(int i=h-1; i>=0; i--) { num>>=1; if(!(a&num)&&!(b&num))return false; if((a&num)&&(b&num))cnt++; if(!(a&num)||!(b&num)) { if(cnt%2)return false; else cnt=0; } } if(cnt%2)return false; return true; } int main() { while(scanf("%d%d",&w,&h),w||h) { if((h*w)%2) { puts("0"); } else { if(h>w) { int t=w; w=h; h=t; } for(int i=0; i< 1<<h; i++) { for(int j=0; j< 1<<h; j++) { vis[i][j]=judge(i,j); } } for(int i=1; i<=w; i++) { for(int j=0; j<1<<h; j++) { if(i==1) { dp[1][j]=(int)vis[(1<<h)-1][j]; } else { dp[i][j]=0; for(int k=0; k<1<<h; k++) { if(vis[k][j])dp[i][j]+=dp[i-1][k]; } } } } printf("%lld\n",dp[w][(1<<h)-1]); } } return 0; }