O(1) 的小乐
豆瓣账号:http://www.douban.com/people/sosisarah/

这个题目非常赞! 给定一个矩形,要求用1*2 的格子进行覆盖,有多少种覆盖方法呢?

dp[i][j] 当状态为j,且第i行已经完全铺满的情况下的种类数有多少种?j中1表示占了,0表示没有被占。

很显然,当每行被放了之后,有一些状态是不可能的,我们这里用1 表示竖着放,0表示横着放。 所以两个0 要相邻,这是程序中的s。

我们每一状态转移,枚举每一个可能的状态,我们希望dp[i][j] 中的j呈现出s[k] 的状态,依次来进行状态转移。

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

vector<int> s;  // possible state
long long dp[13][1<<12];  // dp[i][j]  the number of (row i state j)

int main()
{
    //freopen("1.txt","r",stdin);
    int M,N;
    while(cin>>M>>N && M!=0 && N!=0)
    {
        s.clear();
        if(M*N%2) {cout<<0<<endl; continue;}
        memset(dp,0,sizeof(dp));
        // 0-0 pair
        for(int tag = 0; tag < (1<<N); tag++)
        {
            for(int i=0; i<N; )
            {
                if(tag & (1<<i)) i++;
                else
                {
                    if( i+1< N && !(tag&(1<<(i+1)))) i+=2;
                    else break;
                }
                if(i== N) s.push_back(tag);
            }
        }
        for(int i=0; i<s.size(); i++) dp[0][s[i]] = 1;
        for(int step = 1; step< M; step++)
        {
            for(int tag = 0; tag < (1<<N); tag++)
            {
                for(int i=0; i<s.size(); i++)
                {
                    if((tag & s[i]) != tag) continue;
                    dp[step][tag^ s[i]] += dp[step-1][tag];
                }
            }
        }
        cout<<dp[M-1][0]<<endl;
    }
    return 0;
}
posted on 2014-04-17 13:06  O(1)的小乐  阅读(166)  评论(0编辑  收藏  举报