Mondriaan's Dream(poj 2411)

题意:在n*m的方格里铺1*2的骨牌,有多少种方案

/*
    第一次做插头DP,感觉和状压差不多。
    这道题是利用上一行的状态来更新下一行的状态。
    1代表上一行这个位置填了一个竖的(即本行可以填);
    0代表填了一个横的或者是竖的方格的第二行(即本行可以填)。 
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#define N 12
using namespace std;
int n,m;
long long dp[N][1<<N];
void dfs(int s,int ss,int y,int x){
    if(y>m-1){
        dp[x+1][ss]+=dp[x][s];
        return;
    }
    if(s&(1<<y)){//如果x行y列填的是竖的,那么x+1行y列就没法填
        dfs(s,ss,y+1,x);
        return;
    }
    dfs(s,ss|(1<<y),y+1,x);//填一个竖的
    if(y<=m-2&&!(s&(1<<y+1)))//如果x+1行y+1列可以填,那就可以在y列填一个横的 
        dfs(s,ss,y+2,x);
}
int main(){
    while(scanf("%d%d",&n,&m)&&n&&m){
        if((n*m)&1){
            printf("0
");
            continue;
        }
        if(n==1||m==1){
            printf("1
");
            continue;
        }
        if(n<m) swap(n,m);
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(int i=0;i<n;i++)
            for(int j=0;j<(1<<m);j++){
                if(!dp[i][j]) continue;
                dfs(j,0,0,i);
            }
        cout<<dp[n][0]<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/harden/p/6556963.html