Keshawn_lu's Blog

Leetcode 790. 多米诺和托米诺平铺

字数统计: 505阅读时长: 2 min
2022/11/12 Share

题目简介:

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

lc-domino

给定整数 n ,返回可以平铺 2 x n 的面板的方法的数量。返回对 109 + 7 取模 的值。

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

示例 1:

lc-domino1

1
2
3
输入: n = 3
输出: 5
解释: 五种不同的方法如上所示。

提示:

  • 1 <= n <= 1000

思路:

动态规划,第i列的正方形有四种被覆盖的情况

  • 一个正方形都没有被覆盖,记为状态 0;
  • 只有上方的正方形被覆盖,记为状态 1;
  • 只有下方的正方形被覆盖,记为状态 2;
  • 上下两个正方形都被覆盖,记为状态 3。

考虑第 i - 1 列和第 i 列正方形,它们之间的状态转移如下图(红色条表示新铺的瓷砖):

1

因此:

  • dp[i][0] = dp[i - 1][3]
  • dp[i][1] = dp[i - 1][0] + dp[i - 1][2]
  • dp[i][2] = dp[i - 1][0] + dp[i - 1][2]
  • dp[i][3] = dp[i - 1][0] + dp[i - 1][1] + dp[i - 1][2] + dp[i - 1][3]

初始化dp[1][3] = 1, dp[1][0] = 1。(代表n = 1的情况)

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
int numTilings(int n) {

int mod = pow(10, 9) + 7;

vector<vector<int>> dp(n + 1, vector<int>(4));

dp[1][3] = 1;
dp[1][0] = 1;

for(int i = 2; i <= n; i++){

dp[i][0] = dp[i - 1][3]; //第i列什么都不覆盖
dp[i][1] = (dp[i - 1][0] + dp[i - 1][1]) % mod; //第i列只覆盖上面
dp[i][2] = (dp[i - 1][0] + dp[i - 1][2]) % mod; //第i列只覆盖下面
dp[i][3] = (((dp[i - 1][0] + dp[i - 1][1]) % mod + dp[i - 1][2]) % mod + dp[i - 1][3]) % mod; //第i列全覆盖
}

return dp[n][3];
}
};
CATALOG
  1. 1. 题目简介:
  2. 2. 思路:
  3. 3. 代码如下: