We have two types of tiles: a 2x1 domino shape, and an "L" tromino shape. These shapes may be rotated.

XX  <- domino

XX  <- "L" tromino
X

Given N, how many ways are there to tile a 2 x N board? Return your answer modulo 10^9 + 7.

(In a tiling, every square must be covered by a tile. Two tilings are different if and only if there are two 4-directionally adjacent cells on the board such that exactly one of the tilings has both squares occupied by a tile.)

Example:
Input: 3
Output: 5
Explanation:
The five different ways are listed below, different letters indicates different tiles:
XYZ XXZ XYY XXY XYY
XYZ YYZ XZZ XYY XXY

Note:

  • N  will be in range [1, 1000].

这道题是关于多米诺骨牌和三格骨牌的,其中由两个方形格子组成的是多米诺骨牌(音译,即为双格骨牌),而由三个方形格子组成的‘L’型的是三格骨牌,但其实本质还是个拼格子的问题,并没有利用到骨牌酷炫的连倒技能,倒反而更像是俄罗斯方块中的形状。说是有一个2xN大小的棋盘,我们需要用这些多米诺和三格骨牌来将棋盘填满,问有多少种不同的填充方法,结果需要对一个超大数取余。那么根据博主多年的经验,对于这种求极值,并且超大的情况下,只能使用动态规划Dynamic Programming来做,什么暴力递归神马的,等着爆栈吧。

既然决定了要用DP来做,那么首先就来设计dp数组吧,这里我们就用一个一维的dp数组就行了,其中dp[i]表示填满前i列的不同填法总数对超大数10e^9+7取余后的结果。那么DP解法的难点就是求状态转移方程了,没什么太好的思路的时候,就从最简单的情况开始罗列吧。题目中给了N的范围是[1, 1000],那么我们来看:

当N=1时,那么就是一个2x1大小的棋盘,只能放一个多米诺骨牌,只有一种情况。

当N=2时,那么就是一个2x2大小的棋盘,如下图所示,我们有两种放置方法,可以将两个多米诺骨牌竖着并排放,或者是将其横着并排放。

当N=3时,那么就是一个3x2大小的棋盘,我们共用五种放置方法,如下图所示。仔细观察这五种情况,我们发现其时时跟上面的情况有联系的。前两种情况其实是N=2的两种情况后面加上了一个竖着的多米诺骨牌,第三种情况其实是N=1的那种情况后面加上了两个平行的横向的多米诺骨牌,后两种情况是N=0(空集)再加上两种三格骨牌对角摆开的情况。

当N=4时,那么就是一个4x2大小的棋盘,我们共用十一种放置方法,太多了就不一一画出来了,但是其也是由之前的情况组合而成的。首先是N=3的所有情况后面加上一个竖着多米诺骨牌,然后是N=2的所有情况加上两个平行的横向的多米诺骨牌,然后N=1再加上两种三格骨牌对角摆开的情况,然后N=0(空集)再加上两种三格骨牌和一个横向多米诺骨牌组成的情况。

N=5的情况博主没有再画了,可以参见ZhengKaiWei大神的帖子中的手稿图,很萌~

根据目前的状况,我们可以总结一个很重要的规律,就是dp[n]是由之前的dp值组成的,其中 dp[n-1] 和 dp[n-2] 各自能贡献一种组成方式,而dp[n-3],一直到dp[0],都能各自贡献两种组成方式,所以状态转移方程呼之欲出:

dp[n] = dp[n-1] + dp[n-2] + 2 * (dp[n-3] + ... + dp[0])

= dp[n-1] + dp[n-3] + dp[n-2] + dp[n-3] + 2 * (dp[n-4] + ... dp[0])

= dp[n-1] + dp[n-3] + dp[n-1]

= 2 * dp[n-1] + dp[n-3]

最后化简后的形式就是最终的状态转移方程了,是不是叼的飞起~

class Solution {
public:
int numTilings(int N) {
int M = 1e9 + ;
vector<long> dp(N + );
dp[] = ; dp[] = ; dp[] = ;
for (int i = ; i <= N; ++i) {
dp[i] = (dp[i - ] * + dp[i - ]) % M;
}
return dp[N];
}
};

参考资料:

https://leetcode.com/problems/domino-and-tromino-tiling/discuss/116513/Java-solution-DP

https://leetcode.com/problems/domino-and-tromino-tiling/discuss/116581/Detail-and-explanation-of-O(n)-solution-why-dpn2*dn-1+dpn-3

https://leetcode.com/problems/domino-and-tromino-tiling/discuss/116664/Schematic-explanation-of-two-equivalent-DP-recurrence-formula

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Domino and Tromino Tiling 多米诺和三格骨牌的更多相关文章

  1. [Swift]LeetCode790. 多米诺和托米诺平铺 | Domino and Tromino Tiling

    We have two types of tiles: a 2x1 domino shape, and an "L" tromino shape. These shapes may ...

  2. 【LeetCode】790. Domino and Tromino Tiling 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/domino-a ...

  3. 73th LeetCode Weekly Contest Domino and Tromino Tiling

    We have two types of tiles: a 2x1 domino shape, and an "L" tromino shape. These shapes may ...

  4. leetcode 790. Domino and Tromino Tiling

    We have two types of tiles: a 2x1 domino shape, and an "L" tromino shape. These shapes may ...

  5. 790. Domino and Tromino Tiling

    We have two types of tiles: a 2x1 domino shape, and an "L" tromino shape. These shapes may ...

  6. 动态规划-填格子问题 Domino and Tromino Tiling

    2018-09-01 22:38:19 问题描述: 问题求解: 本题如果是第一看到,应该还是非常棘手的,基本没有什么思路. 不妨先从一种简化的版本来考虑.如果仅有一种砖块,那么,填充的方式如下.

  7. leetcode790 Domino and Tromino Tiling

    思路: dp.没有像discuss中的那样优化递推式. 实现: class Solution { public: ; int numTilings(int N) { vector<vector& ...

  8. 【LeetCode】1128. Number of Equivalent Domino Pairs 等价多米诺骨牌对的数量(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典统计 代码 复杂度分析 日期 题目地址:http ...

  9. LeetCode.1128-等价多米诺骨牌对的数量(Number of Equivalent Domino Pairs)

    这是小川的第394次更新,第428篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第259题(顺位题号是1128).给定多米诺骨牌列表,当且仅当(a == c且b == d ...

随机推荐

  1. java 使用for循环打印杨辉三角形

    首先需要说明的问题: 什么是杨辉三角形? 如图所示:杨辉三角形由数字排列,基本的特点是两侧的数值均为1,其它位置的数值是基正上方的数值与其左上方的数值之和. 代码实现: package test; i ...

  2. Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  3. HP Z620 Windows 7 系统安装(含磁盘阵列)

    由于HP Z620 做了Raid 5磁盘阵列,导致安装系统时,系统加载不了磁盘的驱动,无法将系统安装到硬盘上,正确的方法是:下载SATA驱动,在需要加载驱动的地方,利用另一个U盘,“浏览”解压好的驱动 ...

  4. John von Neumann和Ulam

    John von Neumann和Ulam是好朋友,两人经常在一起喝酒.旅行.谈女人.有一次诺伊曼认出身边的一位女士,他们交谈了几句.随后他给Ulam介绍那是他的一位老朋友,刚刚离婚.Ulam就问:那 ...

  5. Java部分概念理解

    第1部分 方法 1.1 方法基本概念 1) 方法:用于封装一段特定功能代码,尽可能一个方法至只实现一个基本功能,相当于C语言中的函数: 2) 方法可以多次调用: 3) 避免代码冗余,便于维护,便于团队 ...

  6. 消息队列MQ对比

    1.ActiveMQ 是Apache下的一个子项目. 类似于ZeroMQ,它能够以代理人和点对点的技术实现队列.同时类似于RabbitMQ,它少量代码就可以高效地实现高级应用场景.RabbitMQ.Z ...

  7. PHP中ajax返回数据类型为JSON数据的处理

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. Contest2161 - 2019-3-21 高一noip基础知识点 测试4 题解版

    传送门 预计得分:100+100+100+10=310 实际得分:100+0+82+10=192 你们基础知识不行啊——by wxg T1 一看数据范围就是搜索 但是不能因为数据范围就断送了dp的心 ...

  9. # 20175333曹雅坤《Java程序设计》第1周学习总结

    教材学习内容总结 1.学习第一章PPT,安装JRE,JDK并配置path环境参数 2.在windows上使用dos命令运行教材第一章代码Hello.java和People.java 3.下载使用git ...

  10. 【转】解决keepalived正常启动但是虚IP(VIP)没有生成的问题

    如题所示,keepalived安装配置好之后能够正常启动,但是虚IP并没有生成.接着检查防火墙(iptables)发现也没有相关的限制.稍微郁闷了一下之后,查看了keepalived日志文件,这次成功 ...