60_剑指offer_java_n个骰子的点数

本文介绍了一种使用动态规划算法计算多个骰子投掷结果概率的方法。通过构建动态规划数组,逐步增加骰子数量,计算出所有可能点数之和的概率分布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

 

题目描述

测试用例

题目考点

解题思路

参考解题


题目描述

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

测试用例

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

题目考点

  • 考察应聘者的数学建模能力。
  • 考察应聘者对递归和循环的性能的理解。

解题思路

用两个数组来存储骰子点数的每个总数出现的次数(动态规划数组)

n个骰子,n轮

在第一轮循环中,第一个数组中的第n个数字表示骰子和为n出现的次数

在下一轮循环中,我们加上一个新的骰子,此时和为n的骰子出现的次数应该等于上一轮循环中骰子点数和为n-1、n-2、n-3、n-4、n-5与n-6的次数的总和

依次类推求解。

 

对于n个骰子,有以下对应:

下标  i123456m最大值为6 * n
上一轮 p[0]       存储的内容表示当前轮和为m出现的次数  
新一轮 p[1]       增加一个骰子,新一轮和为m出现次数p[1][m] = p[0][m-1] + p[0][m-2] + ……+ p[0][m-j], m >= j 并且 j <= 6  

参考解题

 

package Sword;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 骰子之和
 * 动态规划
 * @author tyler
 *
 */
public class dicesSumSolution {
	// 骰子最大值
	
	int maxValue = 6;
	
	public List<Map.Entry<Integer, Double>> dicesSum(int n) {
		// AbstractMap<K,V>, 此类提供了Map接口的骨架实现,以尽量减少实现此接口所需的工作量。
		List<Map.Entry<Integer, Double>> result = new 
        ArrayList<AbstractMap.Entry<Integer, Double>>();
		
		if (n < 0 ) {
			return result;
		}
		
	// 这里一定要用long型,不能用int型,数大了之后会造成int型溢出
        long[][] probabilities = new long[2][maxValue * n + 1];
        
        // 数组转换标志
        int flag = 0;

        // 初始化第一轮数组p[0],出现1,2,3,4,5,6 的次数为1
        for (int i = 1; i <= maxValue; ++i) {
            probabilities[flag][i] = 1;
        }
        
        // 逐个增加骰子,直到总共n个骰子
        for (int k = 2; k <= n; k++) {
            // 新一轮和为i = 0,1,2,……,k-1的次数不可能存在,令p[1][i] = 0;
            for (int i = 0; i < k; i++) {
                probabilities[1 - flag][i] = 0;
            }
            // 新一轮可能出现的数字为k,k+1,……,k * maxValue,逐个更新其次数
            for (int i = k; i <= maxValue * k; i++) {
                // 首先清空新一轮数组,为更新做准备
            	probabilities[1 - flag][i] = 0;
            	// 新一轮和为i等于上一轮的几个和为i-1,i-2,……,i-j , i >= j 并且 j < maxValue 的总和
                for (int j = 1; j <= i && j <= maxValue; j++) {
                    probabilities[1 - flag][i] += probabilities[flag][i - j];
                }
            }
            // 增加完一个骰子,开始下一个骰子,p[1]变成p[0]
            flag = 1 - flag;
        }
        
        double total = Math.pow(maxValue, n);
        for (int i = n; i <= maxValue * n; i++) {
            result.add(new AbstractMap.SimpleEntry<Integer, Double>(i, probabilities[flag][i] / total));
            // AbstractMap.SimpleEntry<K,V> 保存密钥和值的条目。 该值可以使用setValue方法更改。
            //这个类促进了构建自定义地图实现的过程。 例如,在方法Map.entrySet().toArray中返回SimpleEntry个实例的数组可能很方便 
        }
        return result;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值