[leetcode #790] Domino and Tromino Tiling
4408 ワード
Problem
You have two types of tiles: a 2 x 1 domino shape and a tromino shape. You may rotate these shapes.
Given an integer n, return the number of ways to tile an 2 x n board. Since the answer may be very large, return it modulo 109 + 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 1:
Input: n = 3
Output: 5
Explanation: The five different ways are show above.
Example 2:Input: n = 1
Output: 1
Constraints:・ 1 <= n <= 1000
Idea
これはとても面白い問題です.与えられた2種類のドミノ骨牌を用いて2×n板を作製する場合,いくつかの可能な状況を見つければよい.
もちろんdp解でよいと考え,dpをどのように設計するかを考えた.
まず横長を基準に可能な数を考えた.
1.幅が1の場合、Domino Tileを立てる場合があります.dp(1) = 1
2.幅が2の場合、縦または横に2つのDomino Tileがリストされる場合があります.dp(2) = 2
3.幅が3の場合は、ドミノタイルを立てて2番で作った磁器の板を貼り合わせ、2枚のドミノタイルを水平に作り、1番で作った磁器の板を貼り合わせて、2枚のTrimonoタイルをつなぎます.dp(2) = 2 + 1 + 2
n=4から,前に計算したdpを用いない2つの方法が無条件に存在する.したがって、dp式の作成は以下のようになります.
dp[4]=dp[1]x 2(Trimino tileを使用して幅3のボードを作成)+dp[2]+dp[3]+2(前に作成したボードではなく幅4のボードを作成)
dp[5] = (dp[1] + dp[2]) x 2 + dp[3] + dp[4]
上記の式が出たのは,幅が3より大きい場合,前面に作られたタイルを用いない固有の方法が2つあるためである.
上記の式を用いて、O(N)²)出てきました.通過しましたが、他の解答よりも時間がかかったので、道しるべの解答が見えてきました.
leetcodeのアルゴリズムは次のとおりです.
・ f(1) = 1f(1)=1 because to fully cover a board of width 1, there is only one way, add one vertical domino.
・ f(2) = 2f(2)=2 because to fully cover a board of width 2, there are two ways, either add two horizontal dominos or add two vertical dominos.
・ p(2) = 1p(2)=1 because to partially cover a board of width 2, there is only one way using an L-shaped tromino (leave the upper-right corner uncovered).
・ f(k) = f(k-1) + f(k-2) + 2 * p(k-1)f(k)=f(k−1)+f(k−2)+2∗p(k−1)
・ p(k) = p(k-1) + f(k-2)p(k)=p(k−1)+f(k−2)
Solution
class Solution {
public int numTilings(int n) {
long[] dp = new long[Math.max(n+1,4)];
dp[1] = 1;
dp[2] = 1 + 1;
for (int i=3; i <= n; i++) {
for (int j=1; j < i; j++) {
if (j == 1 || j == 2) {
dp[i] += dp[i-j];
} else {
dp[i] += 2 * dp[i-j];
}
}
dp[i] += 2;
dp[i] %= 1_000_000_007;
}
return (int) (dp[n] % 1_000_000_007);
}
}
次はleetcodeソリューションです.class Solution {
public int numTilings(int n) {
int MOD = 1_000_000_007;
// handle base case scenarios
if (n <= 2) {
return n;
}
// f[k]: number of ways to "fully cover a board" of width k
long[] f = new long[n + 1];
// p[k]: number of ways to "partially cover a board" of width k
long[] p = new long[n + 1];
// initialize f and p with results for the base case scenarios
f[1] = 1L;
f[2] = 2L;
p[2] = 1L;
for (int k = 3; k < n + 1; ++k) {
f[k] = (f[k - 1] + f[k - 2] + 2 * p[k - 1]) % MOD;
p[k] = (p[k - 1] + f[k - 2]) % MOD;
}
return (int) (f[n]);
}
}
Reference
https://leetcode.com/problems/domino-and-tromino-tiling/
Reference
この問題について([leetcode #790] Domino and Tromino Tiling), 我々は、より多くの情報をここで見つけました https://velog.io/@timevoyage/leetcode-790-Domino-and-Tromino-Tilingテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol