POJ 2411 状态压缩DP
2014-04-10 10:58
295 查看
题目来源: http://poj.org/problem?id=2411
题目大意:给一个h*w的方格,现给出1*2和2*1的两种小方块,求出把h*w方格铺满的不同方案数(1<=h,w<=11)
分析:首先能想到的是如果h*w为奇数,那么肯定不能放满,结果为0
如何表示状态:从题目看数据很小,那么很容易想到用二进制来表示状态,0表示当前方格没放,1表示放了
这里用dp[ r ][ cur ]表示前 r-1 行放满,第 r 行状态为 cur 时的方案数,同理,dp[ r-1 ][ lst ]表示前 r-2 行放满,
第 r-1 行状态为 lst 时的方案数; 状态 lst 是由 cur 状态推出来的( [1] 为什么?),
所以dp[ r ][ cur ] = dp[ r ][ cur ] +dp[ r-1 ][ lst ]; 那么dp[ h ][ (1<<w)-1 ] 即为最后所求结果
[1] 先表示一下状态,我们在考虑第 r 行,只考虑前 r 行,一共有 3 种状态(cur表示第 r 行,lst表示第 r-1 行):
1、竖直放 cur<<1 | 1 , lst<<1
2、横着放 cur<<2 | 3, lst<<2 | 3
3、不放 cur<<1, lst<<1 | 1
先解释一下:假设 cur = lst = 0, 假如竖直放,那么 cur = 1, lst = 0, 意思是第 r 行第1列放,第 r-1 行第1列
不放(因为第 r 行要坚直放,所以第 r-1 行第 1 列不能放),直到放完最后一列,出现了两个状态 cur 和 lst,
其中 lst 不就是由 cur 状态推出来的么?并且保证第 r-1 行是满的!
其中第一行只有两种状态,因为第一行上边没有,所以不能竖直放……
举个例子:h = 3, w = 2; dp[ r ][ cur ] += dp[ r-1 ][ lst ];
![](http://img.blog.csdn.net/20140410111914078?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFsaW5nNTIx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
仔细看一看应该就可以看的懂了!下面是代码:
如有错误欢迎指正。
题目大意:给一个h*w的方格,现给出1*2和2*1的两种小方块,求出把h*w方格铺满的不同方案数(1<=h,w<=11)
分析:首先能想到的是如果h*w为奇数,那么肯定不能放满,结果为0
如何表示状态:从题目看数据很小,那么很容易想到用二进制来表示状态,0表示当前方格没放,1表示放了
这里用dp[ r ][ cur ]表示前 r-1 行放满,第 r 行状态为 cur 时的方案数,同理,dp[ r-1 ][ lst ]表示前 r-2 行放满,
第 r-1 行状态为 lst 时的方案数; 状态 lst 是由 cur 状态推出来的( [1] 为什么?),
所以dp[ r ][ cur ] = dp[ r ][ cur ] +dp[ r-1 ][ lst ]; 那么dp[ h ][ (1<<w)-1 ] 即为最后所求结果
[1] 先表示一下状态,我们在考虑第 r 行,只考虑前 r 行,一共有 3 种状态(cur表示第 r 行,lst表示第 r-1 行):
1、竖直放 cur<<1 | 1 , lst<<1
2、横着放 cur<<2 | 3, lst<<2 | 3
3、不放 cur<<1, lst<<1 | 1
先解释一下:假设 cur = lst = 0, 假如竖直放,那么 cur = 1, lst = 0, 意思是第 r 行第1列放,第 r-1 行第1列
不放(因为第 r 行要坚直放,所以第 r-1 行第 1 列不能放),直到放完最后一列,出现了两个状态 cur 和 lst,
其中 lst 不就是由 cur 状态推出来的么?并且保证第 r-1 行是满的!
其中第一行只有两种状态,因为第一行上边没有,所以不能竖直放……
举个例子:h = 3, w = 2; dp[ r ][ cur ] += dp[ r-1 ][ lst ];
仔细看一看应该就可以看的懂了!下面是代码:
#include<iostream> #include<algorithm> #include<cstring> #include<ctime> #include<cmath> #include<string> #include<cstdio> #include<vector> using namespace std; int h, w; long long dp[12][2100]; void dfs(int r, int c, int cur, int lst) { if(r == 1) { // if r == 1 only have two state if(c == w) { dp[r][cur]++; return ; } if(c + 1 <= w) dfs(r, c+1, cur<<1, lst); if(c + 2 <= w) dfs(r, c+2, cur<<2|3, lst); } else { if(c == w) { // one state occurs dp[r][cur] += dp[r-1][lst]; return; } if(c + 1 <= w) { dfs(r, c+1, cur<<1|1, lst<<1); dfs(r, c+1, cur<<1, lst<<1|1); } if(c + 2 <= w) { dfs(r, c+2, cur<<2|3, lst<<2|3); } } } int main() { while(~scanf("%d%d", &h, &w)) { if(h + w == 0) break; if((h*w) & 1) { puts("0"); continue; } if(h < w) swap(h, w); memset(dp, 0, sizeof(dp)); for(int r = 1; r <= h; ++r) dfs(r, 0, 0, 0); printf("%lld\n", dp[h][(1<<w)-1]); } return 0; }
如有错误欢迎指正。
相关文章推荐
- poj 2411 Mondriaan's Dream(压缩状态dp)
- poj 2411 Mondriaan's Dream_状态压缩dp
- poj 2411 Mondriaan's Dream(状态压缩dp)
- poj 2411 Mondriaan's Dream(状态压缩dP)
- HDOJ 1400 & POJ 2411 - Mondriaan's Dream 状态压缩DP
- poj 2411 状态压缩dp
- POJ 2411 Mondriaan's Dream (状态压缩DP)
- POJ 2411 Mondriaan's Dream(状态压缩DP)
- POJ 2411 Mondriaan's Dream 状态压缩DP
- poj 2411 Mondriaan's Dream(状态压缩dp)
- Chapter06-Mondriaan's Dream(POJ 2411)(状态压缩DP)
- POJ-2411 Mondriaan's Dream 状态压缩DP
- POJ 2411 铺地砖 状态压缩dp入门
- poj 2411 Mondriaan's Dream 状态压缩dp
- poj 2411 用1x2填充n*m 状态压缩DP
- poj 2411 (状态压缩dp)
- poj2411之用1*2砖块铺满n*m-状态压缩dp
- pojPOJ 2411--Mondriaan's Dream+状态压缩dp
- poj-2411-状态压缩DP
- POJ 2411 状态压缩DP