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;
}


你可能感兴趣的:(dp,poj,刷题)