【每日一题Day357】LC1155掷骰子等于目标和的方法数 | dp

简介: 【每日一题Day357】LC1155掷骰子等于目标和的方法数 | dp

掷骰子等于目标和的方法数【LC1155】

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

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

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


第一眼很像背包

记忆化
  • 思路

image.png

class Solution {
    public static final int MOD = (int)(1e9 + 7);
    int[][] dp;
    int k;
    public int numRollsToTarget(int n, int k, int target) {
        // 选择n个数,值为1-k,和为target的方案数
        if (n * k < target) return 0;     
        this.k = k;        
        this.dp = new int[n + 1][target + 1];       
        for (int i = 1; i <= n; i++){
            Arrays.fill(dp[i], -1);
        }
        dp[0][0] = 1;
        return dfs(n, target);
    }
    public int dfs(int n, int target){
        if (dp[n][target] != -1) return dp[n][target];
        int res = 0;
        for (int i = 1; i <= Math.min(target, k); i++){            
            res = (res + dfs(n - 1, target - i)) % MOD;         
        }
        dp[n][target] = res;
        return res;
    }
}

image.png

  • 优化:每个数至少取1, 因此可以将target减少n,每个数的范围减小1
递推
  • 实现
class Solution {
    public static final int MOD = (int)(1e9 + 7);
    public int numRollsToTarget(int n, int k, int target) {
        // 选择n个数,值为1-k,和为target的方案数
        if (n * k < target) return 0;            
        int[][] dp = new int[n + 1][target + 1];       
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++){
            for (int j = 1; j <= Math.min(k, target); j++){
                for (int v = j; v <= target; v++){
                    dp[i][v] = (dp[i][v] + dp[i - 1][v - j]) % MOD;
                }
            }
        }
        return dp[n][target];
    }
}


目录
相关文章
|
6月前
【每日一题Day264】LC931下降路径最小和 | dp
【每日一题Day264】LC931下降路径最小和 | dp
40 0
|
6月前
【每日一题Day289】LC1749任意子数组和的绝对值的最大值 | dp
【每日一题Day289】LC1749任意子数组和的绝对值的最大值 | dp
43 0
|
6月前
【每日一题Day211】LC1079活字印刷 | 回溯 计数dp
【每日一题Day211】LC1079活字印刷 | 回溯 计数dp
54 0
|
6月前
【每日一题Day221】LC2455可被三整除的偶数的平均值 | 模拟
【每日一题Day221】LC2455可被三整除的偶数的平均值 | 模拟
48 0
|
6月前
【每日一题Day133】LC2373矩阵中的局部最大值 | 模拟
【每日一题Day133】LC2373矩阵中的局部最大值 | 模拟
49 0
|
6月前
【每日一题Day278】LC2500删除每行中的最大值 | 排序+模拟
【每日一题Day278】LC2500删除每行中的最大值 | 排序+模拟
47 0
|
6月前
【每日一题Day291】LC1289下降路径最小和 II | dp
【每日一题Day291】LC1289下降路径最小和 II | dp
36 0
|
6月前
【每日一题Day236】LC2475数组中不等三元组的数目
【每日一题Day236】LC2475数组中不等三元组的数目
36 0
|
6月前
【每日一题Day152】LC1012至少有1位重复的数字 | 数位dp
【每日一题Day152】LC1012至少有1位重复的数字 | 数位dp
48 0
|
6月前
【每日一题Day358】LC2698求一个整数的惩罚数 | 递归
【每日一题Day358】LC2698求一个整数的惩罚数 | 递归
52 0