poj2411 状态压缩-铺地板题型
Posted zsben991126
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj2411 状态压缩-铺地板题型相关的知识,希望对你有一定的参考价值。
一种做法是先打出所有的状态,即满足上下配对的所有可能方案,然后再逐行进行枚举计数
dp[i][s]=sum{dp[i-1][t]},t是所有和s配对的状态
打状态时要注意如果i-1的j是0,那么i的j必定是1,i剩下的位置要必须一对对填入1,也可以用0填入,即枚举i行的横放砖块的起始位置k即可,如果i-1的k或k+1有一个不是1,那么显然不能放下
/* 对于每一行,用11表示一个横放的方块,用0表示竖放方块的第一格,1表示竖放方块的第二格 枚举i-1行的状态,推出i行的状态 如果i-1行的j位置是0,那么第i行的j必须是1,第i行剩下的地方要么填连续两个1要么填0 第n行的状态必须都是1 */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define ll long long ll dp[15][1<<13]; int n,m,w,path[5000000][2];//所有可能的配对方案 void get(int m){ for(int i=0;i<=(1<<m)-1;i++) for(int j=0;j<=(1<<m)-1;j++){ int ok=1; for(int k=0;k<m;k++) if(ok){ if( !(i&(1<<k)) ){//i的第k位是0 if(!(j&(1<<k))){ ok=0;break; } } else{//i的第k位是1,其实是在枚举j状态横放的起点位置 if(!(j&(1<<k)))continue;//j的第k位是0 ++k; if(k>=m || !(i&(1<<k))){//i没有第k+1位或者i的第k+1位是0,所以j在k位置不可能横放了 ok=0;break; } else if( (j&(1<<(k-1))) && !(j&(1<<k)) ){//j的状态是10,显然不可能 ok=0;break; } } } if(ok)path[w][0]=i,path[w++][1]=j; } } int main(){ while(cin>>n>>m,n){ w=0; if(m>n)swap(n,m); get(m); memset(dp,0,sizeof dp); dp[0][(1<<m)-1]=1; for(int i=0;i<n;i++) for(int j=0;j<w;j++) dp[i+1][path[j][1]]+=dp[i][path[j][0]]; printf("%lld ",dp[n][(1<<m)-1]); } }
以上是关于poj2411 状态压缩-铺地板题型的主要内容,如果未能解决你的问题,请参考以下文章
[POJ 2411] Mondriaan's Dream 状态压缩DP
(hiho1048)POJ2411Mondriaan's Dream(DP+状态压缩 or 轮廓DP)
poj 2411 Mondriaan's Dream 骨牌铺放 状压dp