今天感觉很不错啊,一上来就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;
}