Leetcode.1223 掷骰子模拟
题目链接
Leetcode.1223 掷骰子模拟 Rating : 2008
题目描述
有一个骰子模拟器会每次投掷的时候生成一个 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 1 <= n <= 5000 1<=n<=5000
- r o l l M a x . l e n g t h = = 6 rollMax.length == 6 rollMax.length==6
- 1 < = r o l l M a x [ i ] < = 15 1 <= rollMax[i] <= 15 1<=rollMax[i]<=15
分析:
使用 动态规划 的方式求解。
我们定义 f ( i , j , t i m e s ) f(i,j,times) f(i,j,times) 为投掷了 i
次骰子,并且第 i
个骰子的点数是 j
,且这个 j
的连续出现次数是 times
的不同序列数量。
按照定义,最终返回的结果为 f ( n , 1 , 1 ) + f ( n , 1 , 2 ) + . . . f ( n , 1 , r o l l M a x [ 0 ] ) . . . f ( n , 2 , 1 ) + f ( n , 2 , 2 ) . . . + f ( n , 2 , r o l l M a x [ 1 ] + . . . f ( n , 6 , r o l l M a x [ 5 ] ) f(n,1,1) + f(n,1,2) + ...f(n,1,rollMax[0])...f(n,2,1)+f(n,2,2)...+f(n,2,rollMax[1] + ...f(n,6,rollMax[5]) f(n,1,1)+f(n,1,2)+...f(n,1,rollMax[0])...f(n,2,1)+f(n,2,2)...+f(n,2,rollMax[1]+...f(n,6,rollMax[5])。
即 ∑ j = 1 6 ∑ t i m e s = 1 r o l l M a x [ j − 1 ] f ( n , j , t i m e s ) \sum_{j=1}^{6}\sum_{times=1}^{rollMax[j-1]}f(n,j,times) ∑j=16∑times=1rollMax[j−1]f(n,j,times)。
状态转移:
- 当 当前点
k
不等于 前一个点j
时, f ( i , k , 1 ) = ( f ( i , k , 1 ) + f ( i − 1 , j , t i m e s ) ) m o d 1 0 9 + 7 f(i,k,1) = (f(i,k,1)+f(i-1,j,times)) mod 10^9+7 f(i,k,1)=(f(i,k,1)+f(i−1,j,times))mod109+7 - 当 当前点
k
等于 前一个点j
并且times+1
小于等于rollMax[j-1]
时, f ( i , j , t i m e s + 1 ) = ( f ( i , j , t i m e s + 1 ) + f ( i − 1 , j , t i m e s ) ) m o d 1 0 9 + 7 f(i,j,times+1) = (f(i,j,times+1) + f(i-1,j,times)) mod 10^9+7 f(i,j,times+1)=(f(i,j,times+1)+f(i−1,j,times))mod109+7
时间复杂度: O ( n ∗ 36 ∗ 15 ) O(n * 36 * 15) O(n∗36∗15)
C++代码:
const int MOD = 1e9+7;
using LL = long long;
class Solution {public:int dieSimulator(int n, vector<int>& rollMax) {int f[n+1][7][16];memset(f,0,sizeof f);//初始化只投掷一次骰子的情况for(int i = 1;i <= 6;i++){f[1][i][1] = 1;}for(int i = 2;i <= n;i++){for(int j = 1;j <= 6;j++){for(int times = 1;times <= rollMax[j-1];times++){for(int k = 1;k <= 6;k++){if(j != k) f[i][k][1] = (f[i][k][1] + f[i-1][j][times])%MOD;else if(times + 1 <= rollMax[j - 1]){f[i][j][times+1] = (f[i][j][times+1] + f[i-1][j][times])%MOD;}}}}}LL ans = 0;//统计总的数量for(int j = 1;j <= 6;j++){for(int times = 1;times <= rollMax[j-1];times++) ans += f[n][j][times];}return ans % MOD;}
};
Java代码:
class Solution {private final int MOD = 1000_000_000+7;public int dieSimulator(int n, int[] rollMax) {int [][][] f = new int[n+1][7][16];for(int i = 1;i <= 6;i++){f[1][i][1] = 1;}for(int i = 2;i <= n;i++){for(int j = 1;j <= 6;j++){for(int times = 1;times <= rollMax[j-1];times++){for(int k = 1;k <= 6;k++){if(j != k) f[i][k][1] = (f[i][k][1] + f[i-1][j][times])%MOD;else if(times + 1 <= rollMax[j - 1]){f[i][j][times+1] = (f[i][j][times+1] + f[i-1][j][times])%MOD;}}}}}long ans = 0;for(int j = 1;j <= 6;j++){for(int times = 1;times <= rollMax[j-1];times++) ans += f[n][j][times];}return (int)(ans % MOD);}
}
Leetcode.1223 掷骰子模拟相关推荐
- leetcode - 1223. 掷骰子模拟
1223. 掷骰子模拟 有一个骰子模拟器会每次投掷的时候生成一个 111 到 666 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 iii 的次数不能超过 rollMax ...
- LeetCode 1223. 掷骰子模拟(DP)
1. 题目 有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始 ...
- Leetcode 1223. 掷骰子模拟【动态规划】
有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号). 现 ...
- (C++/Python)LeetCode 1223 掷骰子模拟
自言自语: 做很多动规的题目了,但是总是感觉拿到题目没有思路: 动态规划,就是从0开始变化,或者从后开始变化 所以就是要找到转移方程,dp[i].dp[i][j].dp[i][j][k]中i.j.k代 ...
- 1223. 掷骰子模拟 _动态规划与递归
有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号). 现 ...
- LeetCode 1155. 掷骰子的N种方法(DP)
1. 题目 这里有 d 个一样的骰子,每个骰子上都有 f 个面,分别标号为 1, 2, -, f. 我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和. 如果需要掷出的总点数为 target,请你 ...
- 实验二 利用Excel表格进行掷骰子模拟实验
应用软件:Office2010 我们想分别进行100次和1000次的掷骰子模拟实验.将Excel表格输入成如下样式: 注意!概率的输入是使用=1/6回车计算的,并非手动输入,如图: 类似于投币实验,点 ...
- 使用 Python 进行 GUI 掷骰子模拟
使用 Python 进行 GUI 掷骰子模拟 原文地址 最后更新 : 02 Aug, 2022 在本文中,我们将使用Tkinter和Python中的随机模块创建Rolling The Dices Ga ...
- leetcode - 1155. 掷骰子的N种方法
这里有 ddd 个一样的骰子,每个骰子上都有 fff 个面,分别标号为 1,2,...,f1, 2, ..., f1,2,...,f. 我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和. 如果需 ...
最新文章
- android h5状态栏消息,安卓实现系统状态栏的隐藏和显示
- 我的业务要不要用人工智能?引入AI前你需要评估的(二)
- 2015年最棒的10个 JavaScript 框架
- 如何在windows7和windows8双系统中卸载windows8
- 11g compression 新特性(1)
- 简单记录js中的this关键字
- iOS实现三屏复用循环广告[从服务器请求的广告]
- 2019.01.26 codeforces 1096G. Lucky Tickets(生成函数)
- Lambda、函数式接口、Stream 一次性全给你
- c语言不定参数个数,C语言中不定参数的实现
- sql语句和java的关系_java中Statement 与 PreparedStatement接口之间的关系和区别
- 从一片空白到世界领先,中国通信翻身逆袭史
- error汇总:dpkg: error processing package *** (--configure)
- mysql导出导入数据
- 前端vue导出excel
- Cydia Substrate(iOS)
- “行走的广告牌”——椰树牌椰汁
- java服务端监控平台设计
- 微信投票平台防止刷票的方法和原理随笔
- 三年级计算机帮助我们学本领,三年级学本领100字作文