poj2411

题意:n*m矩形,用1*2的方块填满有多少种方案数? (n,m<=11)

题解:考虑一行一行的填格子,0代表暂时不填,1代表填上。

         那么对于某一行,考虑上一行能转移到它的状态,如果这一行的第j位是0,那么上一行第j位一定是1。

         如果这一行的第j位是1,那么上一行第j位可以是1,也可以是0。

         如果他的上一行第j位是0,那么没有限制,如果他的上一行第j位是1,说明这一行第j位的1一定由横着填来的,那么对上一行第j-1位添加限制,他只能是1.

 

#include<cstdio>
#include<vector>
using namespace std;
const int N=1<<12;
vector<int>G[N];
int n,m;
long long f[N],tmp[N];
void dfs(int id,int p,bool lim,int sum){
    if(p==m){
        if(lim) return;
        G[id].push_back(sum);
        return ;
    }
    if(id&(1<<p)) {
        if(lim) dfs(id,p+1,0,sum+(1<<p));
        else {
            dfs(id,p+1,0,sum);
            dfs(id,p+1,1,sum+(1<<p));
        }
    }
    else {
        if(lim) return;
        dfs(id,p+1,0,sum+(1<<p));
    }
}
int Ju(int x){
    while(x){
        if(x&1){
            x>>=1;
            if(!(x&1)) return 0;
            x>>=1;
        }
        else x>>=1;
    }
    return 1;
}
int main(){
    while(scanf("%d%d",&n,&m),n&&m){
        for(int i=0;i<(1<<m);++i) G[i].clear();
        for(int i=0;i<(1<<m);++i) {
            dfs(i,0,0,0);
        }
        for(int i=0;i<(1<<m);++i) {
            tmp[i]=Ju(i);
        }
        for(int i=2;i<=n;++i) {
            for(int j=0;j<(1<<m);++j) {
                for(int k=0;k<(int)G[j].size();++k) {
                    f[j]+=tmp[G[j][k]];
                }
            }
            for(int j=0;j<(1<<m);++j) {
                tmp[j]=f[j];
                f[j]=0;
            }
        }
        printf("%lld\n",tmp[(1<<m)-1]);
    }    
}

 

posted @ 2018-10-25 13:17 Billyshuai 阅读(...) 评论(...) 编辑 收藏