LC-1155. 掷骰子等于目标和的方法数(记忆化搜索==>动态规划)

1155. 掷骰子等于目标和的方法数

中等

这里有 n 个一样的骰子,每个骰子上都有 k 个面,分别标号为 1k

给定三个整数 n , ktarget ,返回可能的方式(从总共 kn 种方式中)滚动骰子的数量,使正面朝上的数字之和等于 target

答案可能很大,你需要对 109 + 7 取模

示例 1:

输入:n = 1, k = 6, target = 3
输出:1
解释:你扔一个有 6 个面的骰子。
得到 3 的和只有一种方法。

示例 2:

输入:n = 2, k = 6, target = 7
输出:6
解释:你扔两个骰子,每个骰子有 6 个面。
得到 7 的和有 6 种方法:1+6 2+5 3+4 4+3 5+2 6+1。

示例 3:

输入:n = 30, k = 30, target = 500
输出:222616187
解释:返回的结果必须是对 109 + 7 取模。

提示:

  • 1 <= n, k <= 30
  • 1 <= target <= 1000

记忆化搜索 ==> 动态规划

class Solution {
    private static final int MOD = (int)1e9 + 7;
    int n, k, target;
    int[][] cache;
    public int numRollsToTarget(int n, int k, int target) {
        this.n = n;
        this.k = k;
        this.target = target;
        cache = new int[n+1][target+1];
        for(int i = 0; i <= n; i++)  
            Arrays.fill(cache[i], -1);
        return dfs(n, target);
    }

    /**
    定义 dfs(i, tot) 表示还有i个骰子,0-i个骰子投出数字之和为tot,可能的方式
    转移 枚举第 i 个骰子投出 1 - k
        dfs(i-1, tot - j) for j in range(1, k+1)
    递归边界 dfs(0, 0) = 1
            dfs(i, <0) = 0
            dfs(>0, 0) = 0
    递归入口 dfs(n, target)
     */
    public int dfs(int i, int tot){
        if(i == 0 && tot == 0) 
            return 1;
        if(tot < 0 || (i == 0 && tot > 0))
            return 0;
        if(cache[i][tot] >= 0) return cache[i][tot];
        int res = 0;
        for(int j = 1; j <= k; j++){
            res = (res + dfs(i-1, tot - j)) % MOD;
        }
        return cache[i][tot] = res % MOD;
    }
}

记忆化搜索转递推

class Solution {
    private static final int MOD = (int)1e9+7;
    public int numRollsToTarget(int n, int k, int target) {
        int[][] f = new int[n+1][target+1];
        f[0][0] = 1;
        for(int i = 0; i < n; i++){
            for(int tot = 0; tot <= target; tot++){
                for(int j = 1; j <= k; j++){
                    if(tot - j >= 0)
                        f[i+1][tot] = (f[i+1][tot] + f[i][tot - j]) % MOD;
                }
            }
        }
        return f[n][target];
    }
}

空间优化

class Solution {
    private static final int MOD = (int)1e9+7;
    public int numRollsToTarget(int n, int k, int target) {
        int[] f = new int[target+1];
        f[0] = 1;
        for(int i = 0; i < n; i++){
            int[] tmp = Arrays.copyOf(f, f.length);
            Arrays.fill(f, 0);
            for(int tot = 0; tot <= target; tot++){
                for(int j = 1; j <= k; j++){
                    if(tot - j >= 0)
                        f[tot] = (f[tot] + tmp[tot - j]) % MOD;
                }
            }
        }
        return f[target];
    }
}

你可能感兴趣的:(算法刷题记录,1024程序员节)