三、擲骰子模擬(Weekly Contest 158)

題目描述:
有一個骰子模擬器會每次投擲的時候生成一個 1 到 6 的隨機數。

不過我們在使用它時有個約束,就是使得投擲骰子時,連續 擲出數字 i 的次數不能超過 rollMax[i](i 從 1 開始編號)。

現在,給你一個整數數組 rollMax 和一個整數 n,請你來計算擲 n 次骰子可得到的不同點數序列的數量。

假如兩個序列中至少存在一個元素不同,就認爲這兩個序列是不同的。由於答案可能很大,所以請返回 模 10^9 + 7 之後的結果。

示例 1:

輸入:n = 2, rollMax = [1,1,2,2,2,3]

輸出:34
解釋:我們擲 2 次骰子,如果沒有約束的話,共有 6 * 6 = 36 種可能的組合。但是根據 rollMax 數組,數字 1 和 2 最多連續出現一次,所以不會出現序列 (1,1) 和 (2,2)。因此,最終答案是 36-2 = 34。
示例 2:

輸入:n = 2, rollMax = [1,1,1,1,1,1]
輸出:30
示例 3:

輸入:n = 3, rollMax = [1,1,1,2,2,3]
輸出:181

提示:

1 <= n <= 5000
rollMax.length == 6
1 <= rollMax[i] <= 15

emm,兩層的dp好像並不行,看別人實現的用三層來實現的dp

尷尬的呀
在這裏插入圖片描述

class Solution {
    public int dieSimulator(int n, int[] rollMax) {
      int mod = 1000000007;
        long [][][] f= new long[5000][6][16];
        long [] g = new long[6];
        for (int j=0;j<6;j++){
            f[0][j][1] = 1;
            g[j] = 1;
        }
        long now = 6;
        for (int i =1;i<n;i++){
            for (int j=0;j<6;j++){
                for (int k=1;k<=15;k++){
                    if (k == 1){
                        f[i][j][k] = (now - g[j] + mod) % mod;
                    } else if (k<=rollMax[j]){
                        f[i][j][k] = f[i-1][j][k-1];
                    }
                }
            }
            now = 0;
            for (int j=0;j<6;j++) {
                g[j] = 0;
                for (int k = 1; k <= 15; k++) {
                    now = (now+ f[i][j][k] )% mod ;
                    g[j] = (g[j] + f[i][j][k]) % mod;
                }
            }
        }
        return (int)now;

    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章