题面

Description

有一个 r∗cr * cr∗c 的矩形,和一些 1∗21*21∗2 的多米诺骨牌。如果想用这些骨牌刚好填满这个矩
形,使得没有位置是空出来的,多米诺骨牌也没有重叠。请问有多少种方法刚好填
满这个矩形呢?一种可能的填法如下图:

设定矩形是有方向的,旋转之后相同和相互对称的填法应当计算为不同的填法。

Input

一行两个数 r,cr,cr,c。表示矩阵的列数和行数。

Output

一个整数,表示填法总数。

Sample Input

2 11

Sample Output

144

数据范围与约定

20% 数据满足 r,c≤5r,c≤5r,c≤5。
100% 数据满足 r,c≤11r,c≤11r,c≤11。

题解

观察数据范围,很容易想到状压dp,那在这道题中 000 和 111 究竟表示什么呢?横竖?仔细想想这并不好对应二进制数的数位,那应该对应什么呢?

参考自李煜东的解析

观察每行的骨牌,我们会发现只有竖着的上面半截对下一行的排布会造成影响。那我们就可以用二进制数的每一位对应每一列的排布情况,用 111 表示该列是对应的方块是竖着的骨牌的上一半,用 000 表示其它情况。那么f[i][j]f[i][j]f[i][j]表示的则是第 iii 行的分布情况如 jjj 时,前 iii 行总的方案数,其中 jjj 是一个十进制数。
从上一行往下一行转移时,上一行则应满足这些条件:

  1. jjj & kkk 的值为 000,也就是说,上一行与当前行不能有两个同一列的方块都是某个竖着的骨牌的上一半,这很好理解吧,如果这样的话,就与 f[i][j]f[i][j]f[i][j] 的定义矛盾了。
  2. jjj | kkk 的二进制数中连续的 000 的数量必须是偶数。 jjj | kkk 的二进制数什么时候会出现 000 的情况呢?必须是 jjj 和 kkk 的那一位都是 000 ,那这种情况对应的在摆骨牌是是什么样呢?很显然,是上一行与当前这一行都是横着的骨牌时。因为骨牌长为 222 所以连续的 000 的数量也就是横着的骨牌的总长度应该为偶数。那为什么不能是竖着的呢?因为如果是竖着的话,那么上一行的这一列对应的应该是 111 ,执行或运算后得到的值为 111,则不是 000 了,看到这里应该明白了吧,我写到这里时,也才终于想明白,dp真的要自己努力去想,才会一点点的进步。

而满足jjj | kkk 的二进制数中连续的 000 的数量是偶数的数我们可以先预处理出来。

代码如下

for(int i = 0; i < 1 << m; i++) {bool cnt = 0,has_odd = 0;for(int  j = 0; j < m; j++) if(i >> j & 1) has_odd |= cnt,cnt = 0;else cnt ^= 1;in_s[i] = has_odd | cnt ? 0 : 1;}

我在理解这个代码的时候想了很久才想明白,仔细观察能够发现在第一次(每次重复中连续执行 elseelseelse 的第一次)执行 elseelseelse 操作时 cntcntcnt 的值只会是 000,因为此时的 cntcntcnt 要么是 iii 第一位就是 000,要么是在执行了 ififif 操作之后,而每次 ififif 都会把 cntcntcnt 更新为 000 。如果此时出现一段连续的 000,cntcntcnt 则会不断与 111 异或,也就是在 000 和 111 之间不断转换,那么如果 000 的个数是奇数时,最终 cntcntcnt 的值就应该是 111 。而 hasoddhas_oddhaso​dd 则会被或运算更新为 111 而当 hasoddhas_oddhaso​dd 被更新为 111 后它的值就再也不会变化了。不禁感叹位运算的奇妙! 注意我们这里要把 iii 对应的二进制数中前面的 000 也给算进去,因为一共有 mmm 列啊,前面的补进去的 000 也表示着分布情况。所以最后会有当奇数个 000 出现之后前面没有 111 的情况。那么我们 hasoddhas_oddhaso​dd 和 cntcntcnt 中只要有一个为 111,那么 iii 就是不合法的。
呼~自己终于彻底想明白了。

完整代码如下

#include<cstdio>
int n,m;
long long f[12][1 << 11];
bool in_s[1 << 11];
int main() {scanf("%d%d",&m,&n);for(int i = 0; i < 1 << m; i++) {bool cnt = 0,has_odd = 0;for(int  j = 0; j < m; j++) if(i >> j & 1) has_odd |= cnt,cnt = 0;else cnt ^= 1;in_s[i] = has_odd | cnt ? 0 : 1;}f[0][0] = 1;for(int i = 1; i <= n; i++)for(int j = 0; j < 1 << m; j++) {f[i][j] = 0;for(int k = 0;k < 1 << m; k++)if((j & k) == 0 && in_s[j | k])f[i][j] += f[i - 1][k];}printf("%lld",f[n][0]);return 0;
}

21.2.22 T2 多米诺骨牌 真·详解相关推荐

  1. 多米诺骨牌最长牌阵java_棋盘的完美覆盖(多米诺骨牌完美覆盖)幻方(魔方阵)...

    棋盘的完美覆盖: 一张8行8列的棋盘一共有64个方格,用一些形状相同的多米诺骨牌覆盖,每一张覆盖相邻的两个方格,没有相互重叠,能用32张这样的多米诺骨牌完全覆盖整张棋盘称为多米诺骨牌完美覆盖或者盖瓦. ...

  2. puzzle(1036)数邻、多米诺骨牌

    目录 数邻 4*5 5*6 6*7 智力游戏 多米诺骨牌 11多米诺骨牌(1) 23多米诺骨牌(2) 38多米诺骨牌(3)53(4)68(5)81(6)94(7) 106 多米诺骨牌(12)119(8 ...

  3. 腾讯开放将是互联网最大一块多米诺骨牌[转]

    写的很好,随着互联网的格局变化,开放确实是一种趋势. 在你心目中,2009年改变中国互联网行业格局的头件大事是什么? 马云宣布"为1000万中小企业服务.让1亿人就业.给10亿人供应产品&q ...

  4. Blender多米诺骨牌动画学习教程 The Impossible Domino Run in Blender

    流派:电子学习| MP4 |视频:h264,1280×720 |音频:AAC,48.0 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小:8.53 GB 含课程文件 |时长:8h 20 ...

  5. S6 edge+的多米诺骨牌效应:大屏的趋势

    日前,为庆祝三星S6 edge+国行版的顺利发售,三星盖乐世社区的一些粉丝自发组织了三星疯狂"盖星人"第一期活动--活动现场除了可以对S6 edge+进行全方面体验之外,还将演示著 ...

  6. P1282 多米诺骨牌 (差值DP+背包)

    题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S1=6+1+1+1=9, ...

  7. P1282-多米诺骨牌【dp,背包】

    正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P1282 题目大意 n个多米诺骨牌,上下值不相同,可以交换一个多米诺上 ...

  8. 【动态规划】 多米诺骨牌 (ssl 1632/luogu 1282)

    多米诺骨牌多米诺骨牌多米诺骨牌 Description Input 输入文件的第一行是一个正整数n(1≤n≤1000),表示多米诺骨牌数.接下来的n行表示n个多米诺骨牌的点数.每行有两个用空格隔开的正 ...

  9. 【01背包】洛谷P1282多米诺骨牌

    题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S1=6+1+1+1=9, ...

最新文章

  1. 黄聪:分享 SQL Server 2005 分区实现教程
  2. Github标星1.6W+,程序员不得不知的“潜规则”又火了,早知道就不会秃头了
  3. web.xml上下文配置
  4. 为何gpio_to_irq不能静态使用?【转】
  5. MySQL 索引底层数据结构实现
  6. 倒序数(信息学奥赛一本通-T1160)
  7. 切换网段后,处理用友T6变成演示版故障
  8. 京东、宅急送的微服务实践分享(下)| 架构师小组交流会
  9. Loadrunner 11检查点使用方法总结
  10. wps页码从指定页开始_wps怎么自动生成页码以及设置页码从第三页开始
  11. 在线答题助手c语言源码,开源的在线答题小程序
  12. 计算机英语词汇解释,常见计算机英语词汇解释
  13. 动态二级下拉菜单html,jquery实现漂亮的二级下拉菜单代码
  14. JavaScript 技术篇-js正则表达式匹配中英文数字
  15. js实现雪花效果(超简单)
  16. 「机械工程」力矩,转矩,扭矩的理解
  17. Linux上传GitHub【超详细】
  18. Oracle数据库:约束条件:主键约束、唯一约束、检查约束、非空约束、外键约束、默认值填写
  19. SpringMVC从基础到源码
  20. 主域名与子域名的区别

热门文章

  1. 洛谷P3406 海底高铁
  2. hdu1290 献给杭电五十周年校庆的礼物
  3. android UVCCamera could not negotiate with camera:err=-51
  4. (攻防sj)web-bug
  5. 为什么事务普遍加在service层
  6. 【动态规划DP】弹簧板
  7. python代码规范_合格搬砖工
  8. 记一次聚拢Android线程实操
  9. java8 新特性精心整理(全)——新 Date/Time API
  10. 葫芦灸,拥抱葫芦灸走过的日子,不负韶华。