n个骰子的点数 java_n个骰子的点数和为s的概率集合输出(Java)

问题描述:

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

问题分析:

这是一道应用动态规划思想的题目,而动态规划最难的就是要找最优子结构。并采取一种称为备忘录的方法避免重复计算。因为备忘录方法为每个解过的子问题建立了备忘录,以备需要时参看,避免了相同子问题的重复求解。

最优子结构:

F(n, s) 表示n个骰子点数和为s的种数,n表示骰子个数,s表示n个骰子的点数和

F(n, s) = F(n-1, s-1) + F(n-1, s-2) + F(n-1, s-3) + F(n-1, s-4) + F(n-1, s-5) + F(n-1, s-6)

public class Probability {

public void printProbability(int number) { //number为骰子的个数

if (number < 1) return;

int g_maxValue = 6; //骰子的最大点数为6

int[][] probabilities = new int[2][]; //定义两个数组用于保存前一循环的数据供下一阶段使用

probabilities[0] = new int[g_maxValue * number + 1];

probabilities[1] = new int[g_maxValue * number + 1];

int flag = 0; //用于表示轮数交换的表示,当前阶段的信息做下一阶段的输入,上一阶段的信息清空,表示下阶段的输出

//初始化骰子为1时,F(1,s) 的频数

for (int i = 1; i <= g_maxValue; i++)

probabilities[0][i] = 1;

// n表示s要加上第n个骰子朝上的数,也表示n轮大循环

for (int n = 2; n <= number; ++n) {

// 归零操作,因为随着s的变大,F(1,0), F(2,1), F(3,2),...,F(6,5)都不会出现,但是前面计算出现过F(1,1), F(2,2), F(3,3),...,F(5,5),

//因为我们是交替使用前一个数组,所以必须作归零处理

for (int i = 0; i < n; ++i)

probabilities[1 - flag][i] = 0;

//第n轮数据之和为s∈[n, g_maxValue*n],然后计算每一个s的频数

for (int s = n; s <= g_maxValue * n; ++s) {

probabilities[1 - flag][s] = 0; // 第n轮第n个数据初始化为0

//计算F(n, s) = F(n-1, s-1) + F(n-1, s-2) + F(n-1, s-3) + F(n-1, s-4) + F(n-1, s-5) + F(n-1, s-6)

for (int j = 1; j <= s && j <= g_maxValue; ++j)

probabilities[1 - flag][s] += probabilities[flag][s - j];

}

flag = 1 - flag;

}

double total = Math.pow(g_maxValue, number);

for (int i = number; i <= g_maxValue * number; i++) {

double ratio = (double) probabilities[flag][i] / total;

System.out.println(i);

System.out.println(ratio);

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值