题目链接

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 掷骰子模拟相关推荐

  1. leetcode - 1223. 掷骰子模拟

    1223. 掷骰子模拟 有一个骰子模拟器会每次投掷的时候生成一个 111 到 666 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 iii 的次数不能超过 rollMax ...

  2. LeetCode 1223. 掷骰子模拟(DP)

    1. 题目 有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始 ...

  3. Leetcode 1223. 掷骰子模拟【动态规划】

    有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号). 现 ...

  4. (C++/Python)LeetCode 1223 掷骰子模拟

    自言自语: 做很多动规的题目了,但是总是感觉拿到题目没有思路: 动态规划,就是从0开始变化,或者从后开始变化 所以就是要找到转移方程,dp[i].dp[i][j].dp[i][j][k]中i.j.k代 ...

  5. 1223. 掷骰子模拟 _动态规划与递归

    有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号). 现 ...

  6. LeetCode 1155. 掷骰子的N种方法(DP)

    1. 题目 这里有 d 个一样的骰子,每个骰子上都有 f 个面,分别标号为 1, 2, -, f. 我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和. 如果需要掷出的总点数为 target,请你 ...

  7. 实验二 利用Excel表格进行掷骰子模拟实验

    应用软件:Office2010 我们想分别进行100次和1000次的掷骰子模拟实验.将Excel表格输入成如下样式: 注意!概率的输入是使用=1/6回车计算的,并非手动输入,如图: 类似于投币实验,点 ...

  8. 使用 Python 进行 GUI 掷骰子模拟

    使用 Python 进行 GUI 掷骰子模拟 原文地址 最后更新 : 02 Aug, 2022 在本文中,我们将使用Tkinter和Python中的随机模块创建Rolling The Dices Ga ...

  9. leetcode - 1155. 掷骰子的N种方法

    这里有 ddd 个一样的骰子,每个骰子上都有 fff 个面,分别标号为 1,2,...,f1, 2, ..., f1,2,...,f. 我们约定:掷骰子的得到总点数为各骰子面朝上的数字的总和. 如果需 ...

最新文章

  1. android h5状态栏消息,安卓实现系统状态栏的隐藏和显示
  2. 我的业务要不要用人工智能?引入AI前你需要评估的(二)
  3. 2015年最棒的10个 JavaScript 框架
  4. 如何在windows7和windows8双系统中卸载windows8
  5. 11g compression 新特性(1)
  6. 简单记录js中的this关键字
  7. iOS实现三屏复用循环广告[从服务器请求的广告]
  8. 2019.01.26 codeforces 1096G. Lucky Tickets(生成函数)
  9. Lambda、函数式接口、Stream 一次性全给你
  10. c语言不定参数个数,C语言中不定参数的实现
  11. sql语句和java的关系_java中Statement 与 PreparedStatement接口之间的关系和区别
  12. 从一片空白到世界领先,中国通信翻身逆袭史
  13. error汇总:dpkg: error processing package *** (--configure)
  14. mysql导出导入数据
  15. 前端vue导出excel
  16. Cydia Substrate(iOS)
  17. “行走的广告牌”——椰树牌椰汁
  18. java服务端监控平台设计
  19. 微信投票平台防止刷票的方法和原理随笔
  20. 三年级计算机帮助我们学本领,三年级学本领100字作文

热门文章

  1. xilinx license申请(host value ID查看方法)
  2. 电话归属地查询接口地址
  3. Yahoo! 中国搜索使用说明(转)
  4. 绿色astah简体中文版6.8
  5. FlashFXP上传文件没数据,为0KB
  6. 《X Cross:魔境传说》(X Cross)[DVDRip]
  7. 关于adb出现的错误
  8. 隐私泄露无孔不入?扫地机器人已成新型“窃听器”
  9. WordPress安装教程图解
  10. 前端框架 Vue 初探