一、Problem
有一個骰子模擬器會每次投擲的時候生成一個 1 到 6 的隨機數。
不過我們在使用它時有個約束,就是使得投擲骰子時,連續 擲出數字 i 的次數不能超過 rollMax[i](i 從 1 開始編號)。
現在,給你一個整數數組 rollMax 和一個整數 n,請你來計算擲 n 次骰子可得到的不同點數序列的數量。
假如兩個序列中至少存在一個元素不同,就認爲這兩個序列是不同的。由於答案可能很大,所以請返回 模 10^9 + 7 之後的結果。
輸入:n = 2, rollMax = [1,1,2,2,2,3]
輸出:34
解釋:我們擲 2 次骰子,如果沒有約束的話,共有 6 * 6 = 36 種可能的組合。
但是根據 rollMax 數組,數字 1 和 2 最多連續出現一次,所以不會出現序列 (1,1) 和 (2,2)。因
提示:
1 <= n <= 5000
rollMax.length == 6
1 <= rollMax[i] <= 15
二、Solution
方法一:dp
- 定義狀態:
- 表示第 次扔出數字 且數字 連續出現 次的方案數。
- 思考初始化:
- 思考狀態轉移方程:
- 如果 ,
- 如果 ,
- 思考輸出:
class Solution {
public int dieSimulator(int n, int[] rm) {
int mod = (int) 1e9+7, f[][][] = new int[n+1][7+5][16];
for (int j = 0; j < 6; j++) f[1][j][1] = 1;
for (int i = 2; i <= n; i++)
for (int j = 0; j < 6; j++)
for (int k = 1; k <= rm[j]; k++) {
if (k > 1) {
f[i][j][k] = f[i-1][j][k-1];
} else {
int sum = 0;
for (int jj = 0; jj < 6; jj++) if (jj != j) {
for (int kk = 1; kk <= rm[jj]; kk++)
sum = (sum + f[i-1][jj][kk]) % mod;
}
f[i][j][k] = sum;
}
}
int ans = 0;
for (int j = 0; j < 6; j++)
for (int k = 1; k <= rm[j]; k++)
ans = (ans + f[n][j][k]) % mod;
return ans;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,