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. CSS BFC(格式化上下文)深入理解

    什么是BFC 在解释BFC之前,先说一下文档流.我们常说的文档流其实分为定位流.浮动流和普通流三种.而普通流其实就是指BFC中的FC.FC是formatting context的首字母缩写,直译过来是 ...

  2. mybatis LIKE动态参数 sql语句

    @Select({ "select id, vedio_name, vedio_path,vedio_duration, vedio_classify_id, crt_user_id, cr ...

  3. pygame学习点滴

    pygame分为四块 引用/ 初始化/ 事件处理/ 窗口刷新 普通版壁球游戏 """ 引用部分 """ import pygame, sys ...

  4. Lua中的环境概念

    [前言] Lua将其所有的全局变量保存在一个常规的table中,这个table称为“环境”.这种组织结构的优点在于,其一,不需要再为全局变量创造一种新的数据结构,因此简化了Lua的内部实现:另一个优点 ...

  5. vlan 知识学习

    背景     有人反映打印机总是提示ip冲突,经检查,打印机虽然设置了固定ip,但是所有员工在路由器都是设置了DHCP,所以会存在员工占用打印机IP 情况,在路由器添加某一段的ip不自动分配解决此问题 ...

  6. python爬虫解决编码问题

    参考 https://blog.csdn.net/qq_38008452/article/details/80423436 问题 解决方法 加上encoding='utf-8'

  7. [C]关于函数指针参数的赋值

    问题 在有一次尝试用stat()函数获取文件属性的时候,发现如果直接声明一个指针,然后把这个指针作为参数传给函数,会导致函数执行失败,原代码: #include <sys/stat.h> ...

  8. Flask开发微电影网站(四)

    会员中心页面,如下图所示 用户登录后,修改密码页面,如下图所示 用户查看自己的评论页面,如下图所示 用户查看自己的登录日志页面,如下图所示 用户查看自己收藏的电影的页面,如下图所示 1. 定义用户主页 ...

  9. 利用CSS3实现鼠标悬停在图片上图片缓慢缩放的两种方法

    1.改变background-size属性 将图片作为某个html元素的背景图片,用transition属性改变图片的大小. .container{ background-size: 100% 100 ...

  10. Spring Boot 静态资源路径分析

    最近在接触一个看公司的java后台项目(采用的耶鲁大学开源的一个cas单点登录系统),用的是框架是Spring Boot,用的模板是Thymeleaf,于是我生成一个Spring Boot的项目,并且 ...