文章标题 POJ 2411 : Mondriaan's Dream (状态压缩DP)

来源:互联网 发布:python用什么编译器 编辑:程序博客网 时间:2024/06/07 08:29

Mondriaan’s Dream

转自 http://www.cnblogs.com/scau20110726/archive/2013/03/14/2960448.html

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <queue>#include <set>#include <map>#include <algorithm>#include <math.h>#include <vector>using namespace std;typedef long long ll;const int mod=1e9+7;const int maxn=1e5+10;int n,m;ll dp[15][1<<12];bool judge(int x){    for (int i=0;i<m;){        if (x&(1<<i)){            if (i==m-1)return false;            if (x&(1<<(i+1)))i+=2;            else return false;        }        else i++;    }    return true;}bool OK(int now,int pre){    for (int i=0;i<m;){        if ((now&(1<<i))){//第i行第j列为1            if (pre&(1<<i)){//第i-1行第j列也为1,那么第i行必然是横放                //第i行和第i-1行的第j+1都必须是1,否则是非法的                if (i==m-1)return false;                if ((now&(1<<(i+1)))==0)return false;                if ((pre&(1<<(i+1)))==0)return false;                i+=2;            }else {                i++;//第i-1行第j列为0,说明第i行第j列是竖放            }        }else {//第i行第j列为0,那么第i-1行的第j列应该是已经填充了的            if (pre&(1<<i)) i++;//已经填充            else return false;        }    }    return true;}int main(){    while (scanf ("%d%d",&n,&m)&&n&&m){        if ((n&1)&&(m&1)){            printf ("0\n");            continue;        }        if (n<m)swap(n,m);//交换后n是行m是列,m较小,那么状态数也可以相应减少        memset (dp,0,sizeof (dp));        for(int i=0;i<(1<<m);i++){//枚举第一行所有可能的状态            if (judge(i)){                dp[1][i]=1;            }        }        for (int i=2;i<=n;i++){            for (int j=0;j<(1<<m);j++){                for (int k=0;k<(1<<m);k++){                    if (OK(j,k)){                        dp[i][j]+=dp[i-1][k];                    }                }            }        }        printf ("%lld\n",dp[n][(1<<m)-1]);    }    return 0;}
阅读全文
0 0
原创粉丝点击