标签:des style blog http color os strong io
http://poj.org/problem?id=2411
铺砖问题+dfs+状态压缩
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 11507 | Accepted: 6694 |
Description
Input
Output
Sample Input
1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0
Sample Output
1 0 1 2 3 5 144 51205
题意:用1*2的砖去铺h,w的格子,可以横放,也可以竖放。
如果格子h*w为奇数则一定铺不满。
1代表铺,0代表不铺,不铺则下一层一定要铺,抓住下一层一定要把上一层铺满。
第i行只和i-1行有关
枚举i-1行的每个状态,推出由此状态能达到的i行状态
如果i-1行的出发状态某处未放,必然要在i行放一个竖的方块,所以我对上一行状态按位取反之后的状态就是放置了竖方块的状态。
然后用搜索扫一道在i行放横着的方块的所有可能,并且把这些状态累加上i-1的出发状态的方法数,如果该方法数为0,直接continue。
举个例子
2 4
1111
1111
状态可以由
1100 0000 0110 0011 1111
0000 0000 0000 0000 0000
这五种i-1的状态达到,故2 4 的答案为5
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int h,w; __int64 dp[20][2148],add; void dfs(int i,int s,int x) { if(x==w) { //printf("dpi=%d\n",dp[i][s]); dp[i][s]+=add; // printf("i=%d,s=%d,dp=%d\n",i,s,dp[i][s]); return; } dfs(i,s,x+1); if(x<=w-2&&!(s&1<<x)&&!(s&1<<(x+1)))//连续2为不为1.说明上一层没有竖放的。 dfs(i,s|1<<x|1<<(x+1),x+2);//要并起来。 } int main() { int i,j,k,s; while(~scanf("%d%d",&h,&w)) { memset(dp,0,sizeof(dp)); if(h==0&&w==0) break; if((h*w)%2==1) { printf("0\n"); continue; } add=1; dfs(1,0,0); for(i=2;i<=h;i++) { for(j=0;j<1<<w;j++) { if(dp[i-1][j]) { add=dp[i-1][j]; //printf("add=%d\n",add); } else continue; dfs(i,~j&((1<<w)-1),0);//&保证有w位数,比如11可以保证有00011. } } printf("%I64d\n",dp[h][(1<<w)-1]); } return 0; }
poj 2411 Mondriaan's Dream,布布扣,bubuko.com
标签:des style blog http color os strong io
原文地址:http://www.cnblogs.com/cancangood/p/3891452.html