leetcode1155.掷骰子的N种方法

这里有 d 个一样的骰子,每个骰子上都有 f 个面,分别标号为 1, 2, …, f。

我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和。

如果需要掷出的总点数为 target,请你计算出有多少种不同的组合情况(所有的组合情况总共有 f^d 种),模 10^9 + 7 后返回。

示例 1:

输入:d = 1, f = 6, target = 3
输出:1

示例 2:

输入:d = 2, f = 6, target = 7
输出:6

示例 3:

输入:d = 2, f = 5, target = 10
输出:1

示例 4:

输入:d = 1, f = 2, target = 3
输出:0

示例 5:

输入:d = 30, f = 30, target = 500
输出:222616187
 

提示:

1 <= d, f <= 30
1 <= target <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-dice-rolls-with-target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

完整代码

当初想的是回溯思想:将骰子的考虑所有可能的结果和目标值的匹配情况,时间复杂度超级大。
动态规划

  • 定义数组cell[d][target],表示当前有 i 个骰子,目标值为 j 时,有cell[i][j]种方法
  • 状态初始值:不考虑有0个骰子的情况,直接考虑有一个骰子时,进行初始化
  • 状态转移方程:cell[i][j] += cell[i-1][j - k],(k:1…骰子的最大点数f) k是指当前骰子朝上的点数是k
class Solution {
     
public:
    int numRollsToTarget(int d, int f, int target) {
     
        //动态规划
        if(d < 1 || f < 1 || target < 1)
            return 0;
        vector<vector<int>> cell(d, vector<int>(target, 0));
        for(int i = 0; i < d; ++i){
     
            cell[i][0] = 0;
            for(int j = 1; j < target; j++){
     
                if(i == 0){
     
                    if(j + 1 <= f)
                    cell[i][j] = 1;  
                }                   
                else
                    for(int k = 1; k <= f; ++k){
     
                        if(j + 1 - k >= 0)
                        cell[i][j] += cell[i - 1][j - k];
                        cell[i][j] %= (int(pow(10, 9)) + 7);
                    }
            }
        }
        return cell[d - 1][target];
    }
};

你可能感兴趣的:(#,算法,c++)