题目链接: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相关推荐

  1. POJ 2411 Mondriaan‘s Dream(最清楚好懂的状压DP讲解)(连通性状态压缩DP)

    poj 2411 Mondriaan's Dream(最清晰的状压DP解析) 闫氏DP大法好 我们这里是一列一列地来,因为是一个棋盘性的状态压缩DP,从哪个方向都一样 摆放的小方格总方案数 等价于 横 ...

  2. POJ 2411 Mondriaan's Dream [经典状态压缩dp]

    题意:略. 思路:这一题开始做的时候完全没有思路,便去看了别人的题解. 首先,对于这个题目解法想有一个初步的了解,请看这里:http://www.2cto.com/kf/201208/146894.h ...

  3. POJ - 2411 Mondriaan's Dream(状压dp)

    题目链接:点击查看 题目大意:铺瓷砖 题目分析:经典之经典的状态压缩动态规划,具体的懒得说了,怠惰ing..一个月之前写的代码,还好当时注释做的好,现在稍微一看就能立马理解,码到博客上存着吧,三种方法 ...

  4. POJ 2411 Mondriaan's Dream

    题意:用1*2的瓷砖拼出m*n的矩形.问有多少种拼法. 解法:设d[i][j]表示第i行状态为j的情况下,最多能有多少种拼法,对于状态j,1表示为竖着放置的瓷砖且它横跨i和i+1两行,其余皆用0表示. ...

  5. POJ 2411 Mondriaan's Dream(状态压缩DP)

    题目链接 早就见过这个题,开始以为有公式的,推了几次没推出,后来知道这个题是状态压缩DP.最近开始看状态压缩,本想试着解出来,但是这个比那个牛吃草复杂多了...位运算还是不是很熟练,这个题的解题报告有 ...

  6. POJ 2411.Mondriaan's Dream 解题报告

    题意: 给出n*m (1≤n.m≤11)的方格棋盘,用1*2的长方形骨牌不重叠地覆盖这个棋盘,求覆盖满的方案数. Solution:                位运算+状态压缩+dp       ...

  7. poj 2411 Mondriaan#39;s Dream 【dp】

    题目:poj 2411 Mondriaan's Dream 题意:给出一个n*m的矩阵,让你用1*2的矩阵铺满,然后问你最多由多少种不同的方案. 分析:这是一个比較经典的题目.网上各种牛B写法一大堆. ...

  8. POJ 2411 Mondriaan#39;s Dream (dp + 减少国家)

    链接:http://poj.org/problem?id=2411 题意:题目描写叙述:用1*2 的矩形通过组合拼成大矩形.求拼成指定的大矩形有几种拼法. 參考博客:http://blog.csdn. ...

  9. Mondriaan's Dream

    题目链接:http://poj.org/problem?id=2411 题目: Mondriaan's Dream Time Limit: 3000MS Memory Limit: 65536K To ...

最新文章

  1. 启动转换安装失败 拷贝windows安装文件时出错_系统小技巧:“徒手”创建可启动的VHD系统...
  2. 个人永久性免费-Excel催化剂功能第28波-工作薄瘦身,安全地减少非必要冗余
  3. 如何摆脱「自我否定」状态
  4. php mailer altbody,PHPMailer发送邮件中文乱码的解决办法
  5. 一汽大众t一roc_15万元预算能买到的紧凑型SUV——一汽-大众T-ROC探歌
  6. 序列代码UVa 111 History Grading (最长公共子序列)
  7. SuseLinux详解(2)——网络设置静态IP 网关 DNS的方法
  8. RS请求错误之RSV-BBP-0028
  9. 用计算机软件绘制思维导图和手绘思维导图,手绘思维导图与计算机思维导图的对比...
  10. 华为在鸿蒙的另一张王牌,华为的这两张王牌,将助力Mate40系列角逐安卓机皇的位置...
  11. 小米电视3s测试软件,小米盒子3s开箱评测 三大装机必备软件可看凤凰卫视
  12. 高一计算机知识点第一章,第一章计算机基础知识知识点总结
  13. win10电脑用命令行关机
  14. Centos安装Docker的详细安装步骤
  15. 更加精确的TCP Westwood拥塞控制算法
  16. 八股文-ArrayList
  17. 【SEED Labs 2.0】Packet Sniffing and Spoofing Lab
  18. 需求与商业模式创新-需求3-需求工程过程
  19. JavaSE综合项目演练
  20. 关于微信聊天与朋友圈如何快速切换 Mark

热门文章

  1. 2021年5月17号下午初级《会计实务》真题解析
  2. KALI Linux 的下载与安装
  3. python坐标系转换函数_python WGS84和ECEF坐标的转换
  4. 小米Pro安装win7记录
  5. 第二周作业:TGA文件解析
  6. 技术人就得“软硬兼施”
  7. Spring系列:字节跳动+腾讯+华为+小米+阿里面试题分享
  8. 2018-2-13-win10-uwp-音频
  9. unity引擎之Rotation旋转
  10. VBA中MsgBox的几个用法