题目描述

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

[牛客网刷题地址]无

思路分析

  1. 递归的方法。要想求出n个骰子的点数和,可以先把n个骰子分为两堆:第一堆只有一个;另一堆有n-1个。单独的那一个有可能出现1~6的点数。我们需要计算1~6的每一种点数和剩下的n-1个骰子来计算点数和。接下来把剩下的n-1个骰子仍然分成两堆:第一堆只有一个;第二堆有n-2个。我们把上一轮那个单独骰子的点数和这一轮单独骰子的点数相加,再和剩下的n-2个骰子来计算点数和。分析到这里,我们不难发现这是一种递归的思路,递归结束的条件就是最后只剩下一个骰子。我们可以定义一个长度为6n n+1的数组,将和为s的点数出现的次数保存到数组的第s-n个元素里。
  2. 可以换一种思路来解决这个问题。我们可以考虑用两个数组来存储骰子点数的每个总数出现的次数。在一轮循环中,第一个数组中的第n个数字表示骰子和为n出现的次数。在下一轮循环中,我们加上一个新的骰子,此时和为n的骰子出现的次数应该等于上一轮循环中骰子点数和为n-1、n-2、n-3、n-4、n-5与n-6的次数的总和,所以我们把另一个数组的第n个数字设为前一个数组对应的第n-1、n-2、n-3、n-4、n-5与n-6个数字之和。

测试用例

  1. 功能测试:1、2、3、4个骰子的各点数的概率。
  2. 特殊输入测试:输入0。
  3. 性能测试:输入较大的数字,如11。

Java代码

public class Offer060 {
public static void main(String[] args) {
test1();
test2();
test3(); } private static final int maxValue = 6; public static void printProbability1(int number) {
Solution1(number);
} /**
* 方法一:递归解法
*/
private static void Solution1(int number) {
if (number <= 0)
return; // 错误
int[] probabilities = new int[maxValue * number - number + 1];
// 下标为i,对应的值代表点数之和为i+number总共出现的情况次数
// 点数从number~maxValue*number,所以数组大小为6*number-number+1
for (int i = 0; i < probabilities.length; i++)
probabilities[i] = 0; // 计算不同点数出现的次数
for (int i = 1; i <= maxValue; i++)
calP(probabilities, number, number - 1, i); // 第一次掷骰子,总点数只能是1~maxValue(即6) int totalP = (int) Math.pow(maxValue, number); // 所有情况总共出现的次数
for (int i = 0; i < probabilities.length; i++) {
double ratio = (double) probabilities[i] / totalP;
NumberFormat format = NumberFormat.getPercentInstance();
format.setMaximumFractionDigits(2);// 设置保留几位小数
System.out.println("点数和为" + (i + number) + "的概率为:" + format.format(ratio));
}
} /**
* 计算每种点数出现的次数
*
* @param number:骰子总个数
* @param curNumber:当前剩余骰子个数
* @param sum:各个骰子加起来的总点数
*/
private static void calP(int[] probabilities, int number, int curNumber, int sum) {
if (curNumber == 0) {
probabilities[sum - number]++; // 总数为sum的情况存放在sum-number下标中
return;
}
for (int i = 1; i <= maxValue; i++)
calP(probabilities, number, curNumber - 1, sum + i); // 相当于剩余的骰子少一个,总点数增加。
} /**
* 方法二
* @param number
*/
private static void Solution2(int number) {
if (number <= 0)
return; // 错误
int[][] probabilities = new int[2][number * maxValue + 1];
// [2]代表用两个数组交替保存,[number*maxValue+1]是指点数为所在下标时,该点数出现的总次数。
// probabilities[*][0]是没用的,只是为了让下标对应点数
// for (int i = 0; i < 2; i++) {
// for (int j = 0; j < number * maxValue; j++) {
// probabilities[i][j] = 0;
// }
// } for (int i = 1; i <= 6; i++)
probabilities[0][i] = 1; // 第一个骰子出现的情况 int flag = 0;
for (int curNumber = 2; curNumber <= number; curNumber++) { // 当前是第几个骰子
for (int i = 0; i < curNumber; i++)
probabilities[1 - flag][i] = 0; // 前面的数据清零 for (int i = curNumber; i <= curNumber * maxValue; i++) {
for (int j = 1; j <= 6 && j <= i; j++) {
probabilities[1 - flag][i] += probabilities[flag][i - j];
}
}
flag = 1 - flag; } int totalP = (int) Math.pow(maxValue, number); // 所有情况总共出现的次数
for (int i = number; i <= number * 6; i++) {
double ratio = (double) probabilities[flag][i] / totalP;
NumberFormat format = NumberFormat.getPercentInstance();
format.setMaximumFractionDigits(8);// 设置保留几位小数
System.out.println("点数和为" + (i + number) + "的概率为:" + format.format(ratio));
}
} private static void test1() { } private static void test2() { } private static void test3() { } }

代码链接

剑指Offer代码-Java

【Offer】[60] 【n个骰子的点数】的更多相关文章

  1. 剑指 Offer 60. n个骰子的点数 + 动态规划 + 空间优化

    剑指 Offer 60. n个骰子的点数 Offer_60 题目详情 题解分析 package com.walegarrett.offer; /** * @Author WaleGarrett * @ ...

  2. 剑指 Offer 60. n个骰子的点数

    剑指 Offer 60. n个骰子的点数 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s.输入n,打印出s的所有可能的值出现的概率. 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n ...

  3. 【Java】 剑指offer(60) n个骰子的点数

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s.输入n,打 ...

  4. 《剑指offer(第二版)》面试题60——n个骰子的点数

    一.题目描述 把n个骰子仍在地上,所有的骰子朝上的一面的点数之和为s,输入n,打印出s所有可能的值出现的概率. 二.题解 <剑指offer>上给出的两种方法,尤其是代码,晦涩难懂且没有注释 ...

  5. 《剑指offer》面试题60. n个骰子的点数

    问题描述 把n个骰子扔在地上,所有骰子朝上一面的点数之和为s.输入n,打印出s的所有可能的值出现的概率. 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i ...

  6. 【剑指offer】n个骰子的点数,C++实现

    # 题目 # 思路 # 代码

  7. 《剑指offer》第六十题(n个骰子的点数)

    // 面试题60:n个骰子的点数 // 题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s.输入n,打印出s // 的所有可能的值出现的概率. #include <iostream> ...

  8. 【剑指offer】面试题43:n个骰子的点数

    第一种思路是,每一个骰子的点数从最小到最大,如果为1-6,那么全部的骰子从最小1開始,我们如果一种从左向右的排列,右边的最低,索引从最低開始,推断和的情况. def setTo1(dices, sta ...

  9. [剑指Offer]60-n个骰子的点数

    题意 输入骰子个数n,打印出所有骰子朝上的点的点数之和,及对应的概率. 题解 循环. n个骰子,点数之和在n~6n范围内.计算n个骰子扔出和为m的情况数,等于n-1个骰子扔出m-1,m-2...m-6 ...

随机推荐

  1. vue通信、传值的多种方式(详细)

    转载自https://blog.csdn.net/qq_35430000/article/details/79291287

  2. 佳木斯集训Day1

    23333第一次写博客 其实在佳木斯集训之前我都已经两三个月没打代码了 在佳木斯的时候前几天真心手生,导致了前几次考试考的很差... D1的考试还是比较良心的,T1是一道大模拟,直接枚举最后几位是00 ...

  3. 保存localStorage并访问

    将用户的输入保存至localStorage对象的属性中,这些属性在再次访问时还会继续保持在原位置. 如果你在浏览器中按照fil://URL的方式直接打开本地文件,则文法在某些浏览器中使用存储功能(比如 ...

  4. 一个基于TCP/IP的服务器与客户端通讯的小项目(超详细版)

    1.目的:实现客户端向服务器发送数据 原理: 2.建立两个控制台应用,一个为服务器,用于接收数据.一个为客户端,用于发送数据. 关键类与对应方法: 1)类IPEndPoint: 1.是抽象类EndPo ...

  5. 使用DOM4J 对xml解析操作

    参考自:https://blog.csdn.net/redarmy_chen/article/details/12969219 dom4j是一个Java的XML API,类似于jdom,用来读写XML ...

  6. 洛谷 P2704 [NOI2001]炮兵阵地

    题意简述 给定一张地图,有山地H,平原P,平原可放置炮兵, 炮兵可以攻击沿横向左右各两格,沿纵向上下各两格的区域 求最多放几个炮兵,使他们两两攻击不到 题解思路 枚举第i层,第i - 1层,第i - ...

  7. cs231n---生成模型

    1 生成模型的定义和分类 生成模型是一种无监督学习方法.其定义是给一堆由真实分布产生的训练数据,我们的模型从中学习,然后以近似于真实的分布来产生新样本. 生成模型分为显式和隐式的生成模型: 为什么生成 ...

  8. 防抖(debounce)和节流(throttle)

    场景说明:一般我们在前端页面中会给元素绑定click.scroll.onmousemove.resize等事件,这些事件的执行函数如果是去发请求获取数据的话,我们无意识的连续点击或者连续滚动会给服务器 ...

  9. Spring Cloud与Dubbo的完美融合之手「Spring Cloud Alibaba」

    很早以前,在刚开始搞Spring Cloud基础教程的时候,写过这样一篇文章:<微服务架构的基础框架选择:Spring Cloud还是Dubbo?>,可能不少读者也都看过.之后也就一直有关 ...

  10. 如何:从 bool? 安全地强制转换为 bool(C# 编程指南)

    bool? 可以为 null 的类型可以包含三个不同的值:true.false 和 null.因此,bool? 类型不能用于条件语句,如 if.for 或 while.例如,此代码无法编译,并将报告编 ...