首页 > 其他分享 >790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题

790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题

时间:2022-11-21 17:04:18浏览次数:46  
标签:return cur int 多米诺 状态机 range let 托米 MOD

题目描述

这是 LeetCode 上的 ​​790. 多米诺和托米诺平铺​​ ,难度为 中等

Tag : 「状态机 DP」

有两种形状的瓷砖:一种是 ​​2 x 1​​​ 的多米诺形,另一种是形如 ​​"L"​​ 的托米诺形。两种形状都可以旋转。

790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端

给定整数 ​​n​​​ ,返回可以平铺 ​​2 x n​​​ 的面板的方法的数量。返回对 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_i++_02

平铺指的是每个正方形都必须有瓷砖覆盖。两个平铺不同,当且仅当面板上有四个方向上的相邻单元中的两个,使得恰好有一个平铺有一个瓷砖占据两个正方形。

示例 1:

790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_Java_03

输入: n = 3

输出: 5

解释: 五种不同的方法如上所示。

示例 2:

输入: n = 1

输出: 1

提示:

  • 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_04

状态机 DP

定义 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_05 为无须考虑前 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_06 列(含义为前 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_06 列已铺满),当前第 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_08 列状态为 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_09

其中 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_09 取值范围为 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_i++_11

790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_12

为了方便,我们人为规定列数从 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_13

由于骨牌只能在 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_i++_14

790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_15

分别对应「第一列不放置任何骨牌」和「第一列竖着放一块 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_16

790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_17790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_18 由于没法在棋盘左侧以外的位置放置骨牌,不存在合法方案,其值均为 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_19

同时可知 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_20

不失一般性考虑 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_05

  • 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_22 : 需要前 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_06 列铺满,同时第 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_08 列没有被铺,只能由 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_i++_25 转移而来,即有 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_26

这里需要尤其注意:虽然我们能够在上一步留空第 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_06 列,然后在 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_06 列竖放一块 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_16

但我们不能从 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_30 转移到 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_22,因为此时放置的骨牌,仅对第 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_06 列产生影响,不会对第 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_08 列产生影响,该决策所产生的方案数,已在 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_34

  • 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_35 : 可由 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_36 转移而来(见下图),其中 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_37,即有 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_38
  • 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_39 : 可由 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_30790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_41
  • 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_状态机_42 : 可由 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_30790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_44

Java 代码:

class Solution {
int MOD = (int)1e9+7;
public int numTilings(int n) {
int[][] f = new int[n + 10][4];
f[1][0] = f[1][1] = 1;
for (int i = 2; i <= n; i++) {
f[i][0] = f[i - 1][1];
int cur = 0;
for (int j = 0; j < 4; j++) cur = (cur + f[i - 1][j]) % MOD;
f[i][1] = cur;
f[i][2] = (f[i - 1][0] + f[i - 1][3]) % MOD;
f[i][3] = (f[i - 1][0] + f[i - 1][2]) % MOD;
}
return f[n][1];
}
}

TypeScript 代码:

function numTilings(n: number): number {
const MOD = 1e9+7
const f = new Array<Array<number>>()
for (let i = 0; i <= n; i++) f[i] = new Array<number>(4).fill(0)
f[1][0] = f[1][1] = 1
for (let i = 2; i <= n; i++) {
f[i][0] = f[i - 1][1]
let cur = 0
for (let j = 0; j < 4; j++) cur = (cur + f[i - 1][j]) % MOD
f[i][1] = cur
f[i][2] = (f[i - 1][0] + f[i - 1][3]) % MOD
f[i][3] = (f[i - 1][0] + f[i - 1][2]) % MOD
}
return f[n][1]
}

Python3 代码:

class Solution:
def numTilings(self, n: int) -> int:
f = [[0] * 4 for _ in range(n + 10)]
f[1][0] = f[1][1] = 1
for i in range(2, n + 1):
f[i][0] = f[i - 1][1]
f[i][1] = sum([f[i - 1][j] for j in range(4)])
f[i][2] = f[i - 1][0] + f[i - 1][3]
f[i][3] = f[i - 1][0] + f[i - 1][2]
return f[n][1] % 1000000007
  • 时间复杂度:790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_45
  • 空间复杂度:790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_45

滚动数组优化

利用 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_47 仅依赖于 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_算法_34,我们可以采用「滚动数组」方式将其空间优化至 790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_i++_49

Java 代码:

class Solution {
int MOD = (int)1e9+7;
public int numTilings(int n) {
int[][] f = new int[2][4];
f[1][0] = f[1][1] = 1;
for (int i = 2; i <= n; i++) {
int a = i & 1, b = (i - 1) & 1;
f[a][0] = f[b][1];
int cur = 0;
for (int j = 0; j < 4; j++) cur = (cur + f[b][j]) % MOD;
f[a][1] = cur;
f[a][2] = (f[b][0] + f[b][3]) % MOD;
f[a][3] = (f[b][0] + f[b][2]) % MOD;
}
return f[n & 1][1];
}
}

TypeScript 代码:

function numTilings(n: number): number {
const MOD = 1e9+7
const f = new Array<Array<number>>()
for (let i = 0; i <= 1; i++) f[i] = new Array<number>(4).fill(0)
f[1][0] = f[1][1] = 1
for (let i = 2; i <= n; i++) {
const a = i & 1, b = (i - 1) & 1
f[a][0] = f[b][1]
let cur = 0
for (let j = 0; j < 4; j++) cur = (cur + f[b][j]) % MOD
f[a][1] = cur
f[a][2] = (f[b][0] + f[b][3]) % MOD
f[a][3] = (f[b][0] + f[b][2]) % MOD
}
return f[n & 1][1]
}

Python3 代码:

class Solution:
def numTilings(self, n: int) -> int:
f = [[0] * 4 for _ in range(2)]
f[1][0] = f[1][1] = 1
for i in range(2, n + 1):
a, b = i & 1, (i - 1) & 1
f[a][0] = f[b][1]
f[a][1] = sum([f[b][j] for j in range(4)])
f[a][2] = f[b][0] + f[b][3]
f[a][3] = f[b][0] + f[b][2]
return f[n & 1][1] % 1000000007
  • 时间复杂度:790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_后端_45
  • 空间复杂度:790. 多米诺和托米诺平铺 : 简单状态机 DP 运用题_i++_49

最后

这是我们「刷穿 LeetCode」系列文章的第 ​​No.790​​ 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。


标签:return,cur,int,多米诺,状态机,range,let,托米,MOD
From: https://blog.51cto.com/acoier/5874277

相关文章

  • 2022NOIP A层联测30 分配 串串超人 多米诺游戏 大师
    T1[数论/贪心构造]给出n-1对限制形如(i,j,a,b),要求\(xi/xj=a/b\),xi和xj都是正整数。求长度是n的序列x,满足条件(保证给定条件和任意一个数可以唯一确定这个序列)的\(min(\su......
  • 状态机编码方式:二进制binary、独热码 one-hot、格雷码 gray
    关于有限状态机中常用的三种编码方式各自的优缺点 二进制编码:优点:每次加一,编码方式简单;压缩编码,使用寄存器少缺点:翻转次数多,功耗大;易出现毛刺;状态跳转需要组合逻辑多;......
  • 状态机的技术选型,yyds!
    前言今天跟大家分享一个关于“状态机”的话题。状态属性在我们的现实生活中无处不在。比如电商场景会有一系列的订单状态(待支付、待发货、已发货、超时、关闭);员工提交请......
  • Leetcode第790题:多米诺和托米诺平铺(Domino and tromino tiling)
    解题思路采用动态规划思路。参考题解。核心代码如下:constlonglongmod=1e9+7;classSolution{public:intnumTilings(intn){vector<vector<lo......
  • 790. 多米诺和托米诺平铺
    790.多米诺和托米诺平铺有两种形状的瓷砖:一种是 2x1的多米诺形,另一种是形如 "L"的托米诺形。两种形状都可以旋转。给定整数n,返回可以平铺 2xn的面板的方法......
  • 790. 多米诺和托米诺平铺
    790.多米诺和托米诺平铺题解:dpnum数组表示的是:i-1列的瓷砖都被铺满了,第i列的状态枚举第i列的状态枚举有4种:11表示上下两行都被填充,10表示上面那行被填充,01......
  • 【深入浅出 Yarn 架构与实现】2-4 Yarn 基础库 - 状态机库
    当一个服务拥有太多处理逻辑时,会导致代码结构异常的混乱,很难分辨一段逻辑是在哪个阶段发挥作用的。这时就可以引入状态机模型,帮助代码结构变得清晰。一、状态机库概述一......
  • 多米诺骨牌
    1128.等价多米诺骨牌对的数量icintnumEquivDominoPairs(int[][]dominoes){intans=0;int[]a=newint[100];for(int[]cur:dominoes){Arrays.sort(cur);......
  • Wdf框架之WdfObject状态机(2) 一文再补充
      万万没想到<Wdf框架之WdfObject状态机(2)>的内容如此之多,2篇博客的篇幅还不够承载,需要第三篇来完成最后一击。本文将进入FxObject::DeleteWorkerAndUnlock的else分支......
  • 1007. 行相等的最少多米诺旋转
    1007.行相等的最少多米诺旋转在一排多米诺骨牌中,A[i]和B[i] 分别代表第i个多米诺骨牌的上半部分和下半部分。(一个多米诺是两个从1到6的数字同列平铺形成的 ......