POJ 2411: Mondriaan's Dream
题目链接:http://poj.org/problem?id=2411
题意:
用1*2的骨牌填充一个n*m的网格。
求方案数。
算法:
这道题用普通的状态压缩DP的话,打表也可以过。
也就是用一个m位二进制数,0表示上一行的这个位置未被覆盖,1表示被覆盖。
然后逐行转移。
不过我用朴素的状态压缩优化到死的时候,也就知道这题一定有别的解法。
先来介绍一种用二进制枚举子集的方法,是zkc同学之前教给我的。
假设有一个集合S,它的元素是0~(k-1)中的一部分。
用一个k位二进制数mask代表这个集合。
mask的第x位为1表示x在这个集合中,
否则x不在这个集合中。‘
那么下面这个语句可以不重不漏的枚举出S的所有子集
for(int mask1=mask; mask1>=0; mask1=(mask1-1)&mask)
原理也比较简单。
当某一次-1操作使得原本不该出现1的地方出现了1。
也就是说,出现了一个不合法的后缀(这个后缀肯定是一连串的1)
那么&操作就相当于是在合法的前缀不变的情况下,这些不合法的后缀“跨过去”了。
直观地看,就是把这些1“减去”了。
在这个过程中,一定没有漏掉任何合法的情形,
因为这些1不减去的话肯定是不合法的。
这道题与以上的情形正好相反。
当我们知道上一行的覆盖情况,那么上一行未被覆盖的格子下一行必定要覆盖,
也就是有些格子是必取的。
那么可以用下面这个语句枚举出下一行的所有情形。
for(int mask1=mask; mask1<(1<<m); mask1=(mask 1+1)|mask)
当然,要求除了与上一行相接的格子(竖直放置骨牌)外,
其它被覆盖的格子要是两两一组的。
这个判断一下就可以了。
代码如下:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
using namespace std;const int MAXN=11;
long long d[MAXN+1][MAXN+1][1<<MAXN];
int m;bool judge(int mask)
{while(mask){if(mask&1){if((mask&3)!=3){return false;}mask>>=2;}else{mask>>=1;}}return true;
}int main()
{memset(d,0,sizeof(d));for(m=1; m<=11; m++){d[0][m][(1<<m)-1]=1LL;for(int i=0; i<11; i++){for(int mask1=0; mask1<(1<<m); mask1++){int mask=(~mask1)&((1<<m)-1);for(int mask2=mask; mask2<(1<<m); mask2=(mask2+1)|mask){if(judge(mask2^mask)){d[i+1][m][mask2]+=d[i][m][mask1];}}}}}int a,b;while(scanf("%d%d",&a,&b),(a||b)){printf("%I64d\n",d[a][b][(1<<b)-1]);}return 0;
}
PS:
在网上看到纳米兄的解题报告是用插头DP中的轮廓线解决的,深感不明觉厉。
不过最近确实事情太多,过一段时间好好的学习一下插头DP,再来重做这题。
POJ 2411: Mondriaan's Dream相关推荐
- POJ 2411 Mondriaan‘s Dream(最清楚好懂的状压DP讲解)(连通性状态压缩DP)
poj 2411 Mondriaan's Dream(最清晰的状压DP解析) 闫氏DP大法好 我们这里是一列一列地来,因为是一个棋盘性的状态压缩DP,从哪个方向都一样 摆放的小方格总方案数 等价于 横 ...
- POJ 2411 Mondriaan's Dream [经典状态压缩dp]
题意:略. 思路:这一题开始做的时候完全没有思路,便去看了别人的题解. 首先,对于这个题目解法想有一个初步的了解,请看这里:http://www.2cto.com/kf/201208/146894.h ...
- POJ - 2411 Mondriaan's Dream(状压dp)
题目链接:点击查看 题目大意:铺瓷砖 题目分析:经典之经典的状态压缩动态规划,具体的懒得说了,怠惰ing..一个月之前写的代码,还好当时注释做的好,现在稍微一看就能立马理解,码到博客上存着吧,三种方法 ...
- POJ 2411 Mondriaan's Dream
题意:用1*2的瓷砖拼出m*n的矩形.问有多少种拼法. 解法:设d[i][j]表示第i行状态为j的情况下,最多能有多少种拼法,对于状态j,1表示为竖着放置的瓷砖且它横跨i和i+1两行,其余皆用0表示. ...
- POJ 2411 Mondriaan's Dream(状态压缩DP)
题目链接 早就见过这个题,开始以为有公式的,推了几次没推出,后来知道这个题是状态压缩DP.最近开始看状态压缩,本想试着解出来,但是这个比那个牛吃草复杂多了...位运算还是不是很熟练,这个题的解题报告有 ...
- POJ 2411.Mondriaan's Dream 解题报告
题意: 给出n*m (1≤n.m≤11)的方格棋盘,用1*2的长方形骨牌不重叠地覆盖这个棋盘,求覆盖满的方案数. Solution: 位运算+状态压缩+dp ...
- poj 2411 Mondriaan#39;s Dream 【dp】
题目:poj 2411 Mondriaan's Dream 题意:给出一个n*m的矩阵,让你用1*2的矩阵铺满,然后问你最多由多少种不同的方案. 分析:这是一个比較经典的题目.网上各种牛B写法一大堆. ...
- POJ 2411 Mondriaan#39;s Dream (dp + 减少国家)
链接:http://poj.org/problem?id=2411 题意:题目描写叙述:用1*2 的矩形通过组合拼成大矩形.求拼成指定的大矩形有几种拼法. 參考博客:http://blog.csdn. ...
- Mondriaan's Dream
题目链接:http://poj.org/problem?id=2411 题目: Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K To ...
最新文章
- 启动转换安装失败 拷贝windows安装文件时出错_系统小技巧:“徒手”创建可启动的VHD系统...
- 个人永久性免费-Excel催化剂功能第28波-工作薄瘦身,安全地减少非必要冗余
- 如何摆脱「自我否定」状态
- php mailer altbody,PHPMailer发送邮件中文乱码的解决办法
- 一汽大众t一roc_15万元预算能买到的紧凑型SUV——一汽-大众T-ROC探歌
- 序列代码UVa 111 History Grading (最长公共子序列)
- SuseLinux详解(2)——网络设置静态IP 网关 DNS的方法
- RS请求错误之RSV-BBP-0028
- 用计算机软件绘制思维导图和手绘思维导图,手绘思维导图与计算机思维导图的对比...
- 华为在鸿蒙的另一张王牌,华为的这两张王牌,将助力Mate40系列角逐安卓机皇的位置...
- 小米电视3s测试软件,小米盒子3s开箱评测 三大装机必备软件可看凤凰卫视
- 高一计算机知识点第一章,第一章计算机基础知识知识点总结
- win10电脑用命令行关机
- Centos安装Docker的详细安装步骤
- 更加精确的TCP Westwood拥塞控制算法
- 八股文-ArrayList
- 【SEED Labs 2.0】Packet Sniffing and Spoofing Lab
- 需求与商业模式创新-需求3-需求工程过程
- JavaSE综合项目演练
- 关于微信聊天与朋友圈如何快速切换 Mark