状态压缩DP POJ 2411 Mondriaan's Dream
来源:互联网 发布:系统检测安全数据 编辑:程序博客网 时间:2024/05/20 01:36
题目:
Description
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!
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 21 31 42 22 32 42 114 110 0
Sample Output
10123514451205
这个题目,讲道理思路是很多的。
但是要想找到合适的方式来表达状态,确实不容易。
如果不是今天在这之前做了另外一个题目:棋盘问题
我可能还真不会想到这个方法。
代码:
#include<iostream>#include<string.h>using namespace std;int h, w;long long dp[11][2048];//前i行的和long long sum;//对于每一行,横为0,竖为1,所以00011是不可能的,00100是可能的bool ok(int n)//每2个0都是在一起的{n += (1 << w);//因为不知道维度的奇偶性while (n){if (n % 2)n /= 2;else{if (n % 4)return false;n /= 4;}}return true;}int main(){while (cin >> h >> w){if (h == 0)break;if (h == 1){cout << (w + 1) % 2 << endl;continue;}if (h % 2 && w % 2){cout << 0 << endl;continue;}memset(dp, 0, sizeof(dp));for (int i = 0; i < (1 << w); i++)if(ok(i))dp[0][i] = 1;for (int i = 1; i < h-1; i++){for (int j = 0; j < (1 << w); j++){for (int k = 0; k < (1 << w); k++){if (j&k)continue;if (ok(j^k)){dp[i][j] += dp[i - 1][k];}}}}sum = 0;for (int k = 0; k < (1 << w); k++)if (ok(k))sum += dp[h - 2][k];cout << sum << endl;}return 0;}
首先,怎么样把一行状态压缩。
如果骨牌是横着的,那么就是00,如果骨牌是竖着的,那么就是1(上面1行或者下面一行也有个1)
然后直接按照顺序串联起来。
然后,dp二维数组是什么呢?
就是前i行的和为j的情况数。
我觉得我并没有说清楚前i行的和是什么鬼,不过不重要,
这么说吧,如果第i行的某个格子是00中的0,或者11中下面的1,那么它对应 j 里面的0,
如果它是11中上面的1,即它和它下面一行的那个格子组成骨牌,那么它对应 j 里面的1。
也就是相当于,画一条横线标明前i行,j 就是那些被割开的骨牌。
1 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---状态压缩)
- poj 2411/hdu 1400 Mondriaan's Dream 状态压缩dp
- poj 2411 Mondriaan's Dream (状态压缩dp 入门)
- HDOJ 1400 & POJ 2411 - 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)
- poj 2411 Mondriaan's Dream 状态压缩DP
- 状态压缩DP POJ 2411 Mondriaan's Dream
- POJ-2411 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
- 结合使用Canvas API与History API——模拟绘图
- MongoDB学习(二) 下载和安装
- PyGobject(一百零八)CSS系列——混合模式
- 第三方支付宝API应用流程
- jpg图片解码
- 状态压缩DP POJ 2411 Mondriaan's Dream
- 操作系统页面置换算法之最优置换(OPT)算法
- 快排,二叉树的逐层遍历(面试常考)
- 添加全局的css样式
- JS中对Cookie的操作详解
- Mac 上升级Ruby
- UnicodeEncodeError: 'ascii' codec can't encode characters in position 9-14
- 杭电1438 钥匙计数一
- logstash-filter-elasticsearch 具体使用实例