POJ 2411_Mondriaan's Dream
题意:
用1*2和2*1的方块将给定长宽的矩形填满。问有多少种放法,对称的算两种。
分析:
状态压缩dp
首先用0表示前一行没有竖块占用这个位置,而1表示该位置和他上方的位置放了一个竖块,从而压缩状态。接下来一行一行的看,每一行都只受上一行的影响,同时影响着下一行的状态,那么如何将现在的状态和下一行的状态联系起来呢?
- 令dp[i][j]表示第i行状态为j时的方案数,直接把两个状态作为参数进行DFS,在到达每行行尾时更新 dp[i+1][next];。
- 看poj的discuss中的方法,对于某一行来说,如果横着放了方块后,就将相应的位置置为1,而被上一行占用的位置也已经是1了,那么整行下来,就只有0的位置是要放竖块的了,而此时下一行对应的位置应该为1,可以发现下一行状态就是这一行状态的非!【感觉好巧妙啊!
因为要求正好填满,所以两种方法最后都可以是输出dp[h+1][0],但是第二种方法也就可以取反直接用dp[h][(1<<w)−1]求。
还有!!位运算注意括号!!
代码:
方法一:
#include<cstdio>
#include<cstring>
const int maxn = 15;
long long dp[maxn][1<<maxn];
int w, h;
void dfs(int a, int b, int now, int next)
{
if(b == w){
dp[a+1][next] += dp[a][now];
return;
}
if(now&(1<<b)) dfs(a, b + 1, now, next);
else {
dfs(a, b+1, now, next|1<<b);
if(b+1< w&&!(now&1<<(b+1)))
dfs(a, b+2, now, next);
}
return;
}
int main (void)
{
while(~scanf("%d%d",&h,&w)&&h+w){
memset(dp, 0, sizeof(dp));
dp[1][0] = 1;
dfs(1,0,0,0);
for(int i = 2; i <= h; i++){
for(int j = 0; j < 1<<w; j++){
if(dp[i][j]) dfs(i, 0, j, 0);
}
}
printf("%I64d\n",dp[h+1][0]);
}
}//266ms
方法二:
#include<cstdio>
#include<cstring>
const int maxn = 15;
long long dp[maxn][1<<maxn];
int w, h;
long long tmp;
void dfs(int a, int b, int now)
{
if(b == w){
dp[a][now] += tmp;
return;
}
dfs(a, b + 1,now);//要么被占要么放竖块
if(b+1<w&&!(now&1<<b)&&!(now&1<<(b+1)))
dfs(a, b+2, now|(1<<b)|(1<<(b+1)));
return;
}
int main (void)
{
while(~scanf("%d%d",&h,&w)&&h+w){
memset(dp, 0, sizeof(dp));
tmp = 1;
dfs(1,0,0);
for(int i = 2; i <= h; i++){
for(int j = 0; j < 1<<w; j++){
if(dp[i-1][j]) {
tmp = dp[i-1][j];
int next = ~j&((1<<w)-1);
dfs(i, 0, next);
}
}
}
printf("%I64d\n",dp[h][(1<<w)-1]);
}
}//250MS
POJ 2411_Mondriaan's Dream的更多相关文章
- POJ 2411Mondriaan's Dream
题目: Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after prod ...
- poj 2411 Mondriaan's Dream 【dp】
题目:id=2411" target="_blank">poj 2411 Mondriaan's Dream 题意:给出一个n*m的矩阵,让你用1*2的矩阵铺满,然 ...
- POJ 2411 Mondriaan's Dream -- 状压DP
题目:Mondriaan's Dream 链接:http://poj.org/problem?id=2411 题意:用 1*2 的瓷砖去填 n*m 的地板,问有多少种填法. 思路: 很久很久以前便做过 ...
- [poj P2411] Mondriaan's Dream
[poj P2411] Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 18023 A ...
- POJ 2411 Mondriaan's Dream 插头dp
题目链接: http://poj.org/problem?id=2411 Mondriaan's Dream Time Limit: 3000MSMemory Limit: 65536K 问题描述 S ...
- Poj 2411 Mondriaan's Dream(压缩矩阵DP)
一.Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, ...
- Mondriaan's Dream POJ - 2411
Mondriaan's Dream POJ - 2411 可以用状压dp,但是要打一下表.暴力枚举行.这一行的状态.上一行的状态,判断如果上一行的状态能转移到这一行的状态就转移. 状态定义:ans[i ...
- POJ 题目2411 Mondriaan's Dream(状压DP)
Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 13519 Accepted: 787 ...
- POJ 2411 Mondriaan's Dream
状压DP Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 9938 Accepted: 575 ...
随机推荐
- c#中stringbuilder的方法总结
String 对象是不可改变的.每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间.在需要对字符串执行重复修改的情况下,与创建新 ...
- java内存查看与分析
业界有很多强大的java profile的工具,比如Jporfiler,yourkit,这些收费的东西我就不想说了,想说的是,其实java自己就提供了很多内存监控的小工具,下面列举的工具只是一小部分, ...
- php的一个魔法常亮__DIR__
我们知道PHP中提供了一个魔术常量(magic constant)__FILE__,用来指向当前执行的PHP脚本.但PHP没有直接提供该脚本所在目录的常量.也就是说如果我们要得到当前PHP脚本所在的目 ...
- table鼠标滑过变颜色
table鼠标滑过变颜色 添加 table tr:hover{background-color: #eee;} 设置鼠标滑过行背景变色,重新刷新浏览器页面. 一般设置灰色,eee
- CAD交互绘制圆(com接口)
CAD绘制图像的过程中,画圆的情况是非常常见的,用户可以在控件视区点取任意一点做为圆心,再动态点取半径绘制圆. 主要用到函数说明: _DMxDrawX::DrawCircle 绘制一个圆.详细说明如下 ...
- java中属性命名get字母大小写问题
java文件 company.java private int sTime; public void setSTime (int sTime) { this.sTime = sTime; ...
- li标签和checkbox绑定
参考原文:https://www.cnblogs.com/youxin/p/3885496.html 我们经常需要li或span包含一个checkbox,不管点击checkbox或li都会触发相应的事 ...
- secureCRT 破解
转自:http://www.cnblogs.com/qingtingzhe/articles/5008902.html
- ORACLE中的游标Cursor总结
游标(Cursor):用来查询数据库,获取记录集合(结果集)的指针,可以让开发者一次访问一行结果集,在每条结果集上作操作. 游标可分为: 1. 静态游标:分为显式(explicit)游标和 ...
- 路径工具类NSPathUtilities
路径工具类NSPathUtilities.h 路径类NSPathUtilities.h包含了 NSString的函数和分类扩展,他允许你操作路径名.应该竟可能的使用这些函数,以便使程序更独立于文件系统 ...