力扣题目链接:https://leetcode.cn/problems/number-of-dice-rolls-with-target-sum/
这里有 n
个一样的骰子,每个骰子上都有 k
个面,分别标号为 1
到 k
。
给定三个整数 n
, k
和 target
,返回可能的方式(从总共 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
开辟一个动态规划数组 d p dp dp,其中 d p [ i ] [ j ] dp[i][j] dp[i][j]代表 i i i个骰子的和为 j j j的方案数。
初始值 d p [ i ] [ j ] = 0 dp[i][j]=0 dp[i][j]=0,而 d p [ 1 ] [ 1 − k ] = 1 dp[1][1-k]=1 dp[1][1−k]=1。
这样,我们就可以从第二天开始枚举:
for i from 2 to n: # i个骰子
for j from 1 to target: # 和为j
for _k from 1 to min(k, target): # i个骰子和为j,可以由 i-1个骰子和为j-_k 加上 一个值为_k的骰子 得到
dp[i][j] = (dp[i][j] + dp[i - 1][j - _k]) % MOD
优化:
复杂的分析
没有进行空间优化:
typedef long long ll;
const ll MOD = 1e9 + 7;
class Solution {
public:
int numRollsToTarget(int n, int k, int target) {
vector<vector<ll>> dp(n + 1, vector<ll>(target + 1, 0));
for (int j = 1; j <= min(k, target); j++) {
dp[1][j] = 1;
}
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= target; j++) {
for (int _k = 1; _k <= min(k, j); _k++) {
dp[i][j] = (dp[i][j] + dp[i - 1][j - _k]) % MOD;
}
}
}
return dp[n][target];
}
};
进行了空间优化:
MOD = int(1e9 + 7)
class Solution:
def numRollsToTarget(self, n: int, k: int, target: int) -> int:
dp = [1] + [0] * target
for i in range(1, n + 1):
for j in range(target, -1, -1):
dp[j] = 0
for _k in range(1, min(k + 1, j + 1)):
dp[j] = (dp[j] + dp[j - _k]) % MOD
return dp[-1]
同步发文于CSDN,原创不易,转载经作者同意后请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/134023955