POJ2411 Mondriaan's Dream 【状压dp】
没错,这道题又是我从LZL里的博客里剽过来的,他的题真不错,真香。
题目链接:http://poj.org/problem?id=2411
题目大意:给一个n * m的矩形, 要求用 1 * 2的小方块去填充满这个矩形, 有多少种填充方式。(1<=n, m <= 11)
思路:
1.凭借做题的经验,能想到这道题一定是无法用暴力去解决,因为方法数肯定很多,暴力跑不出来。
2.看到这题我想到的是用状态转移,因为大的矩形填充可以由多个小的矩形填充来组成,这是最开始的想法,但是这种想法远远不够。
3.用到状压dp,这篇博客讲解的非常清楚:https://blog.csdn.net/u014634338/article/details/50015825
4.总的来说就是先预处理出第一行的所有状态,然后dp从第2行开始,check()本行与前一行的状态是否兼容,然后把相应状态的方法数叠加上来。
5.0代表竖放,竖放的第二个砖块为1. 1代表横放,所占的两个位置都为1
代码里写了很详细的注释:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std; int row, col;
long long dp[][ << ]; //代表前 i 行,第i行状态为j时的方案数目.因此答案所求的是 dp[row][(1 << m) - 1] int ok(int state)
{
for(int j = ; j < col; ) //枚举每一列的状态 前j列已经被确定
{
if(state & ( << j)) //第 j 列为 1
{
if(j == col - ) //列数不够
return ;
if(state & ( << (j + ))) //第 j + 1列为 1, 横放
j += ;
else//第 j + 1 列为 0, 在第 j 列还未被确定的情况下是不合法的
return ;
}
else//第 j 列为 0, 竖放
{
j += ;
}
}
return ;
} int check(int now, int pre)
{
for(int j = ; j < col; )//枚举每一列判断是否与前一行有冲突
{
if(now & ( << j))//第i行第j列为1
{
if(pre & ( << j))//第i-1行第j列也为1,那么第i行必然是横放
{
if(j == col - )
return ;
if(!(now & ( << (j + ))) || !(pre & ( << (j + ))))
//第i行和第i-1行的第j+1都必须是1,否则是非法的
return ;
j += ;
}
else //第i-1行第j列为0,说明第i行第j列是竖放
j += ;
}
else //第i行第j列为0,那么第i-1行的第j列应该是已经填充了的
{
if(pre & ( << j))
j += ;
else
return ;
}
}
return ;
} int main()
{
while(scanf("%d%d", &row, &col) != EOF)
{
if(row == && col == )
break;
if(col > row) //将图较小边作为宽,这样一行中的状态数较少,可以提高效率
swap(col, row);
if((row * col) % ) //若面积为 奇数 , 则不可能存在覆盖满的情况
{
printf("0\n");
continue;
}
mem(dp, );
int tot = << col;
for(int i = ; i < tot; i ++) //枚举第1行的所有状态,初始化第1行的方案数
{
if(ok(i))
dp[][i] = ;
}
for(int i = ; i <= row; i ++) //dp从第2行开始,因为第1行已经预处理了
{
for(int j = ; j < tot; j ++)//第 i 行的状态
{
for(int k = ; k < tot; k ++)//第 i - 1行的状态
{
if(check(j, k))
dp[i][j] += dp[i - ][k];
}
}
}
printf("%lld\n", dp[row][( << col) - ]);
}
return ;
}
POJ2411 Mondriaan's Dream 【状压dp】的更多相关文章
- [poj2411] Mondriaan's Dream (状压DP)
状压DP Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One nigh ...
- POJ 2411 Mondriaan's Dream -- 状压DP
题目:Mondriaan's Dream 链接:http://poj.org/problem?id=2411 题意:用 1*2 的瓷砖去填 n*m 的地板,问有多少种填法. 思路: 很久很久以前便做过 ...
- Poj 2411 Mondriaan's Dream(状压DP)
Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Description Squares and rectangles fascina ...
- POJ 2411 Mondriaan's Dream ——状压DP 插头DP
[题目分析] 用1*2的牌铺满n*m的格子. 刚开始用到动规想写一个n*m*2^m,写了半天才知道会有重复的情况. So Sad. 然后想到数据范围这么小,爆搜好了.于是把每一种状态对应的转移都搜了出 ...
- $POJ2411\ Mondriaan's\ Dream$ 状压+轮廓线$dp$
传送门 Sol 首先状压大概是很容易想到的 一般的做法大概就是枚举每种状态然后判断转移 但是这里其实可以轮廓线dp 也就是从上到下,从左到右地放方块 假设我们现在已经放到了$(i,j)$这个位置 那么 ...
- POJ-2411 Mondriann's Dream (状压DP)
求把\(N*M(1\le N,M \le 11)\) 的棋盘分割成若干个\(1\times 2\) 的长方形,有多少种方案.例如当 \(N=2,M=4\)时,共有5种方案.当\(N=2,M=3\)时, ...
- poj2411 Mondriaan's Dream (轮廓线dp、状压dp)
Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 17203 Accepted: 991 ...
- POJ 2411 Mondriaan'sDream(状压DP)
题目大意:一个矩阵,只能放1*2的木块,问将这个矩阵完全覆盖的不同放法有多少种. 解析:如果是横着的就定义11,如果竖着的定义为竖着的01,这样按行dp只需要考虑两件事儿,当前行&上一行,是不 ...
- POJ2411 - Mondriaan's Dream(状态压缩DP)
题目大意 给定一个N*M大小的地板,要求你用1*2大小的砖块把地板铺满,问你有多少种方案? 题解 刚开始时看的是挑战程序设计竞赛上的关于铺砖块问题的讲解,研究一两天楞是没明白它代码是怎么写的,智商捉急 ...
- POJ2411 Mondriaan's Dream 题解 轮廓线DP
题目链接:http://poj.org/problem?id=2411 题目大意 给你一个 \(n \times m (1 \le n,m \le 11)\) 的矩阵,你需要用若干 \(1 \time ...
随机推荐
- python mysql插入中文乱码
# "INSERT INTO" 语句sql = "INSERT INTO sites (name, url, status, enable) VALUES (%s, %s ...
- Luogu P4141 消失之物 背包 分治
题意:给出$n$个物品的体积和最大背包容量$m$,求去掉一个物品$i$后,装满体积为$w\in [1,m]$背包的方案数. 有 N 个物品, 体积分别是 W1, W2, …, WN. 由于她的疏忽, ...
- Java进阶知识10 Hibernate一对多_多对一双向关联(Annotation+XML实现)
本文知识点(目录): 1.Annotation 注解版(只是测试建表) 2.XML版 的实现(只是测试建表) 3.附录(Annotation 注解版CRUD操作)[注解版有个问题:插入值时 ...
- 【CUDA 基础】6.0 流和并发
title: [CUDA 基础]6.0 流和并发 categories: - CUDA - Freshman tags: - 流 - 事件 - 网格级并行 - 同步机制 - NVVP toc: tru ...
- kubernetes 之部署metrics-server v0.3.1
Metrics-server简介 Metrics-server是用来替换heapster获取集群上资源指标数据的,heapster从1.11开始逐渐被废弃了. 在使用heapster时,获取资源指标是 ...
- Codeforces 1238E. Keyboard Purchase
传送门 注意到 $m$ 只有 $20$ ,考虑一下状压 $dp$ 设 $f[S]$ 表示当前确定的字符集合为 $S$ ,那么转移就考虑从最右边加入的下一个字符 $c$ 那么问题来了,代价如何计算 考虑 ...
- LK光流算法公式详解
由于工程需要用到 Lucas-Kanade 光流,在此进行一下简单整理(后续还会陆续整理关于KCF,PCA,SVM,最小二乘.岭回归.核函数.dpm等等): 光流,简单说也就是画面移动过程中,图像上每 ...
- 什么是跨平台性?原理是什么?JVM
所谓跨平台性,是指java语言编写的程序,一次编译后,可以在多个系统平台上运行. 实现原理:Java程序是通过java虚拟机在系统平台上运行的,只要该系统可以安装相应的java虚拟机,该系统就可以运行 ...
- 脚本:将git项目下载到本地并启动
大致思路:从git上clone源代码到本地:使用mvn package将源代码达成war/jar包:将打好的包放到tomcatpath/webapps/下:到tomcatpath/bin/下执行res ...
- springboot多个数据源
1.启动两个mysql,可以按照如下操作使用docker来部署mysql容器,比较简单 https://www.cnblogs.com/qq931399960/p/11527222.html 2.如果 ...