一.题目描述

  把n个骰子仍在地上,所有的骰子朝上的一面的点数之和为s,输入n,打印出s所有可能的值出现的概率。

二.题解

  《剑指offer》上给出的两种方法,尤其是代码,晦涩难懂且没有注释。而n个骰子的问题实质就是一个动态规划问题,所以文本主要从动态规划的角度来求解这个问题。首先该问题具备DP的两个特征:最优子结构性质和子问题的重叠性。具体的表现在:(1)n个骰子的点数依赖于n-1个骰子的点数,相当于在n-1个骰子点数的基础上再进行投掷。(2)求父问题的同时,需要多次利用子问题。由此定义状态转移方程为$f(n,k)$表示$n$个骰子点数和为$k$时出现的次数,于是可得:

$$ f(n,k) = f(n- 1, k- 1) + f(n- 1, k- 2) + f(n- 1, k- 3) + f(n- 1, k- 4) + f(n- 1, k- 5) + f(n- 1, k- 6) $$

其中 $n > 0$且$k <= 6n$。其中$f(n-1,k-i)$表示的是第n次掷骰子时,骰子的点数为$i$对应的情况,所以从$k-1$到$k-6$分别对应第n次掷骰子时骰子正面为$1$到$6$的情况。而初始状态可以定义为:

$$ f(1,1) = f(1,2) = f(1,3) = f(1,4) = f(1,5) = f(1,6) = 1 $$

所以根据这两个方程,给出的实现代码如下:

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
#include<stack>
#define MAX_NUM 100
using namespace std; void FindSum(int n)
{
if(n <= 0)
return;
int sum = 0;
int arr[n + 1][6 * n + 1];
memset(arr,0,sizeof(arr));
for(int i = 1; i <= 6; i++)//初始状态
arr[1][i] = 1;
for(int i = 2; i <= n; i++)//状态转移方程
{
for(int j = i; j <= 6*i; j++)//注意j的范围受i影响
{
arr[i][j] += (arr[i - 1][j - 1] + arr[i - 1][j - 2] + arr[i - 1][j - 3] + arr[i - 1][j - 4] + arr[i - 1][j - 5]
+arr[i - 1][j - 6]);
}
}
//输出结果
for(int i = n; i <= 6 * n; i++)
{
//cout<<"骰子的和为 "<<i<<" 时,对应的次数为:"<<arr[n][i]<<endl;
sum += arr[n][i];
}
cout<<n<<"个骰子总共的次数为 "<<sum<<endl;
for(int i = n; i <= 6 * n; i++)
{
cout<<"骰子的和为 "<<i<<" 时,对应的频率为:"<<(arr[n][i] * 1.0 / sum)<<endl;
} }
int main()
{
int n;
cout<<"请输入骰子的个数:"<<endl;
cin>>n;
FindSum(n);
}

此处的代码只是朴素dp的实现,用动态规划来解释,感觉比书上好理解多了....

参考:https://blog.csdn.net/k346k346/article/details/50988681

《剑指offer(第二版)》面试题60——n个骰子的点数的更多相关文章

  1. 《剑指offer(第二版)》面试题55——判断是否为平衡二叉树

    一.题目大意 输入一颗二叉树,判断该二叉树是否为平衡二叉树(AVL树). 二.题解 <剑指offer>上给出了两种解决方式: 1.第一种是从根节点开始,从上往下遍历每个子节点并计算以子节点 ...

  2. 经典面试题目——找到第n个丑数(参考《剑指offer(第二版)》面试题49)

    一.题目大意 给你一个数n,要求返回第n个丑数.其中,丑数的定义如下: 丑数是指只包含因子2.3和5的数.(数字1也是丑数,不过是个特例)引用<剑指offer>上的话来说,对于一个数M,如 ...

  3. 《剑指offer(第二版)》——面试题36:二叉搜索树与双向链表

    具体的题目大意和参考思路在此处不详述(见<剑指offer>),实质就是在中序遍历的过程中调整指针的指向,关于中序遍历有递归和非递归两种操作,所以此处也用了两种方法. 方法1(递归法): 代 ...

  4. 《剑指offer(第二版)》面试题64——求1+2+...+n

    一.题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字以及条件判断语句 (即三元运算符,A? B : C) 二.题解 虽然求和问 ...

  5. 结合《剑指offer(第二版)》面试题51来谈谈归并排序

    一.题目大意 给定一个数组A,对于数组A中的两个数字,如果排在前面的一个数字大于(必须大于,等于不算)后面的数字,则这两个数字组成一个逆序对.要求输出数组A中的逆序对的总数.例如,对于数组{7,5,6 ...

  6. 《剑指offer 第二版》题解

    剑指Offer 按题号排序 面试题 3:数组中重复的数字 面试题 4:二维数组中的查找 面试题 5:替换空格 面试题 6:从头到尾打印链表 面试题 7:重建二叉树 面试题 8:二叉树的下一个节点 面试 ...

  7. 剑指offer第二版-10.斐波那契数列

    面试题10:斐波那契数列 题目要求: 求斐波那契数列的第n项的值.f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2) n>1 思路:使用循环从下往上计算数列. 考点:考察对递归 ...

  8. 剑指offer第二版-5.替换空格

    面试题5:替换空格 题目要求: 实现一个函数,把字符串中的每个空格都替换成“%20”,已知原位置后面有足够的空余位置,要求改替换过程发生在原来的位置上. 思路: 首先遍历字符串求出串中空格的数量,求出 ...

  9. 剑指offer第二版-3.数组中重复的数

    面试题3:数组中重复的数 题目要求: 在一个长度为n的数组中,所有数字的取值范围都在[0,n-1],但不知道有几个数字重复或重复几次,找出其中任意一个重复的数字. 解法比较: /** * Copyri ...

随机推荐

  1. SQA计划与系统测试

    (一)目的 本计划的目的是定义我们该小组所做的“爱上长大”项目的SQA任务和职责,在项目过程中应遵循的流程.规范和约定等,以确保软件质量得到维持. (二)范围 本计划应用于“爱上长大”项目开发的整个生 ...

  2. 您只能在 HTML 输出中使用 document.write。如果您在文档加载后使用该方法,会覆盖整个文档

    https://blog.csdn.net/qq_37425546/article/details/54868908

  3. C# Main函数中调用异步方法的2种实现

    As you discovered, in VS11 the compiler will disallow an async Main method. This was allowed (but ne ...

  4. Flyweight 享元(结构型)

    一:描述:(该模式实际应用较少) Flyweight 享元模式是对大量细粒度的元素进行共享和重用.减少对象的创建减轻内存: 注和单例模式不同的是:享元模式的各个对象佣有各自的行为并可实例化,单例模式的 ...

  5. 调试利器GDB(下)

    本节我们研究gdb更深层的用法: 数据断点: 可以根据变量的值来监视变量. 数据断点本质是硬件断点,数量有限. watch var_name告诉gdb我们关注var_name这个变量,如果它的值被改变 ...

  6. matlab中如何用rand产生相同的随机数

    直接给链接:rand()产生相同随机数

  7. jmeter 获取登录token

    1.在登录的请求下新建正则表达式,获取token 2.正则表达式的写法 注意:apply to 默认是选择第二个,但是有获取不到token的情况就选第一个 "accessToken" ...

  8. HTML下标签之应用

    <!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...

  9. SSH(Spring+Struts2+Hibernate) of mappings(SSH三大框架的映射问题)

    错误提示: org.springframework.orm.hibernate3.HibernateSystemException: Unknown entity org.hibernate.Mapp ...

  10. JavaScript之更改闭包内的变量值

    var f = function( ) { var x = 1 function fo() { console.log( x++ ) }   return fo } var fn = f() fn() ...