POJ2411Mondriaan's Dream(DP+状态压缩 or 插头DP)
2017-12-03 19:51
471 查看
问题:
Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series' (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways.Expert as he was in this material, he saw at a glance that he'll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won't turn into a nightmare!
Input
The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.
Output
For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.
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
到底是这么想到用01和11的,是不是有一类这样处理的题型呢?
这种题一般都有很多优化,包括很多预处理;或者运算方式的优化,比如尽量用位运算;或者有多个check时优先check哪一个。
这里实现了两种情况避免了暴力check(据说还有很多优化,但是代码肯定没我现在这么短了,嘻嘻哒):
α,上(x)下(y)不能同时为0,则一定是x|y==(1<<m)-1。这样就不需要一位一位check
β,上(x)下(y)同为1的连续个数需要为偶,即z=x&y中1必须成连续偶数次出现。我们预先处理各种z,避免了每次都check。
这里的写法应该是归类为插头DP还是轮廓线DP还是其他?不清楚,我已经混了,或者本来就是交叉没有明确界限的。还可以用轮廓DP的思想来解决,过几天再试一试。
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<cmath> using namespace std; long long dp[1<<12][12];int n,m; bool ok[1<<12]; void getok() { for(int i=0;i<(1<<11);i++){ ok[i]=true; for(int j=0;j<11;j++) if(i&1<<j){ int cnt=1; while(i&(1<<(j+1))) cnt++,j++; if(cnt&1){ok[i]=false ;break;} } } } bool check(int x,int y) { if((x|y)!=((1<<m)-1)) return false; //上下不能同时为0 return ok[x&y];//上下同时为1要满足连续时为偶。 } int main() { int i,j,k; getok(); while(~scanf("%d%d",&n,&m)){ if(n==0&&m==0) return 0; memset(dp,0,sizeof(dp)); dp[(1<<m)-1][0]=1; for(i=1;i<=n;i++) for(k=0;k<(1<<m);k++) for(j=0;j<(1<<m);j++) if(check(k,j)) dp[j][i]+=dp[k][i-1]; printf("%lld\n",dp[(1<<m)-1] ); } return 0; }
相关文章推荐
- 【POJ2411】Mondriaan's Dream-状态压缩DP(插头DP?)
- POJ3254Corn Fields (状态压缩or插头DP)
- zoj 1100&& poj2411 Mondriaan's Dream (dfs&&枚举&&状态压缩dp)好题
- poj 2411 && zoj 1100 Mondriaan's Dream ———状态压缩dp
- poj 2411 Mondriaan's Dream(状态压缩dp)
- Mondriaan's Dream(DP-之状态压缩的动态规划poj2411)
- poj 2411 Mondriaan's Dream 状态压缩dp
- 【poj2411】Mondriaan's Dream 状态压缩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)
- 【poj2411】Mondriaan's Dream 状态压缩dp
- POJ 2411 Mondriaan's Dream 状态压缩DP
- 插头与轮廓线与基于连通性状态压缩的dp 学习指南
- POJ 2411 Mondriaan's Dream 状态压缩DP
- POJ 2411 Mondriaan's Dream (状态压缩DP)
- POJ-2411 Mondriaan's Dream 状态压缩DP
- hdu 1400 Mondriaan's Dream(DP+状态压缩)
- POJ 2411 Mondriaan's Dream(状态压缩DP)