这里有 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
解题思路
这个问题首先不难想到通过DFS
来做。我们可以定义函数 f ( i , j ) f(i,j) f(i,j),其中 i i i表示几个骰子, j j j表示我们的目标值是多少。那么
然后通过记忆化的方式加速计算即可。
from functools import lru_cache
class Solution:
def numRollsToTarget(self, d: int, f: int, target: int) -> int:
mod = 10**9 + 7
@lru_cache(None)
def dfs(m, t):
if m < 0 or t < 0:
return 0
if m == 0 and t == 0:
return 1
res = 0
for i in range(1, f + 1):
res = (res + dfs(m - 1, t - i)) % mod
return res
return dfs(d, target)
我们也可以通过动态规划的方式来写
class Solution:
def numRollsToTarget(self, d: int, f: int, target: int) -> int:
mod = 10**9 + 7
mem = [[0]*(target + 1) for _ in range(d + 1)]
mem[0][0] = 1
for i in range(1, d + 1):
for j in range(1, f + 1):
for k in range(j, target + 1):
mem[i][k] = (mem[i][k] + mem[i-1][k-j]) % mod
return mem[-1][-1]
但是动态规划的效率没有前一种高。
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!