1223 掷骰子模拟(动态规划)

1. 问题描述:

有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数。

不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号)。

现在,给你一个整数数组 rollMax 和一个整数 n,请你来计算掷 n 次骰子可得到的不同点数序列的数量。

假如两个序列中至少存在一个元素不同,就认为这两个序列是不同的。由于答案可能很大,所以请返回 模 10^9 + 7 之后的结果。

示例 1:

输入:n = 2, rollMax = [1,1,2,2,2,3]
输出:34
解释:我们掷 2 次骰子,如果没有约束的话,共有 6 * 6 = 36 种可能的组合。但是根据 rollMax 数组,数字 1 和 2 最多连续出现一次,所以不会出现序列 (1,1) 和 (2,2)。因此,最终答案是 36-2 = 34。

示例 2:

输入:n = 2, rollMax = [1,1,1,1,1,1]
输出:30
示例 3:

输入:n = 3, rollMax = [1,1,1,2,2,3]
输出:181

提示:

  • 1 <= n <= 5000
  • rollMax.length == 6
  • 1 <= rollMax[i] <= 15

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/dice-roll-simulation

2. 思路分析:

① 一开始的时候感觉像是可以使用数学方法来计算问题,但是后面发现计算起来很混乱,会忽略某些情况或者多计算一些情况,在领扣的评论区中发现大多数使用的是动态规划来解决的,其中我感觉有一个大佬写的代码思路比较清晰,也比较好理解,所以自己改写了对应的python版本

② 首先需要声明一个三维的列表,dp[i][j][k]表示的意思是第i次投掷点数为j连续的出现的次数为k,能够想到使用高维度的dp来解决的思路还是比较厉害的,我们在一开始初始化的时候可以将其第一次投掷的对应的点数为k的连续次数为1次的dp数组对应位置设置为1,表示连续的次数为1,接下来第一层循环表示的是i + 1次投掷,第二层循环j表示的意思是当前投掷的点数,第三层循环表示的意思是上一次投掷的点数

③ 当我们发现当前投掷的点数与上一次投掷的点数不一样的时候,那么dp数组为上一次投掷的点数对应的可能的情况的总和,比如当前位置是2,那么上一次的投掷的点数可能是1,3,4,5,6然后累加这些数字出现的可能连续数字的次数的累加和即可,当相同的时候那么更新当前的位置出现的点数连续的次数加1的可能的情况,这些在代码中进行理解会更好一点

④ 大佬的题解:https://leetcode-cn.com/problems/dice-roll-simulation/solution/jin-liang-jian-dan-di-ba-si-lu-jiang-ming-bai-by-m/

3. 代码如下:

from typing import List


class Solution:
    def dieSimulator(self, n: int, rollMax: List[int]) -> int:
        # 三维数组维高/列/行
        dp = [[[0] * 16 for _ in range(7)] for _ in range(n)]
        mod = 10 ** 9 + 7
        # 初始化第一行的数据
        for i in range(1, 7):
            dp[0][i][1] = 1
        for i in range(1, n):  # 第i + 1次抛掷
            for j in range(1, 7):  # 出现的点数为j
                for k in range(1, 7):  # 上一次出现的点数为k
                    if j != k:  # 与上一次的点数不一样
                        for t in range(1, rollMax[k - 1] + 1):
                            # 更新的是当前出现点数为1次的对应位置的值
                            dp[i][j][1] += dp[i - 1][k][t]
                            dp[i][j][1] %= mod
                    else:
                        for t in range(1, rollMax[k - 1]):
                            dp[i][j][t + 1] += dp[i - 1][k][t]
                            dp[i][j][t + 1] %= mod
        sum = 0
        for i in range(1, 7):
            for t in range(1, rollMax[i - 1] + 1):
                sum = (sum + dp[n - 1][i][t]) % mod
        return sum

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/107348839