n 个骰子的点数
Posted ctz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了n 个骰子的点数相关的知识,希望对你有一定的参考价值。
题目
把 n 个骰子扔在地上,所有骰子朝上一面的点数之和为 s。输入 n,打印出 s 的所有可能的值出现的概率。
思路
解法一:
先把 n 个骰子分为两堆:第一堆只有一个,另一个有 n-1 个。单独的那一个有可能出现从 1 到 6 的点数。我们需要计算从 1 到 6 的每一种点数和剩下的 n-1 个骰子来计算点数和。接下来把剩下的 n-1 个骰子还是分成两堆,第一堆只有一个, 第二堆有 n-2 个。我们把上一轮那个单独骰子的点数和这一轮单独骰子的点数相加, 再和剩下的 n-2 个骰子来计算点数和。分析到这里,我们不难发现这是一种递归的思路,递归结束的条件就是最后只剩下一个骰子。
我们可以定义一个长度为“6n-n+1”的数组, 和为 s 的点数出现的次数保存到数组第 s-n 个元素里。
解法二:
我们可以考虑用两个数组来存储骰子点数的每一个总数出现的次数。在一次循环中, 第一个数组中的第 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 之和。
#include <iostream> #include <cmath> using namespace std; const int max_value=6;//单个骰子的最大值 class Solution { public: void probality(int n);//递归 void probality(int original,int index,int curr_sum,int *value); void cricile_probality(int n);//基于循环解法 }; void Solution::probality(int n) { if(n<1) return; int max_sum=n*max_value;//n个骰子的最大值 int *value=new int[max_sum-n+1];//定义6*n-n+1的数组 for(int i=n;i<=max_sum;++i) value[i-n]=0;//将和为s的点数存放到数组的第s-n个元素里 int curr_sum=0; probality(n,n,curr_sum,value); int sum=pow((double)max_value,n); for(int i=n;i<=max_sum;++i) { double ratio=(double)value[i-n]/sum; cout<<i<<‘ ‘<<ratio<<endl; } delete []value; return; } void Solution::probality(int original,int index,int curr_sum,int *value) { if(index==0) { value[curr_sum-original]+=1; return; } for(int i=1;i<=max_value;++i) probality(original,index-1,i+curr_sum,value); } void Solution::cricile_probality(int n) { if(n<1) return; int *value[2]; value[0]=new int[max_value*n+1]; value[1]=new int[max_value*n+1]; for(int i=0;i<max_value*n+1;++i) { value[0][i]=0; value[1][i]=1; } int flag=0;//标记当前使用的是0数组还是1数组 for(int i=1;i<=max_value;++i)//第一次投骰子 value[flag][i]=1; //抛出其他骰子 for(int k=2;k<=n;++k) { for(int i=0;i<k;++i)//如果抛出了k个骰子,那么和为[0, k-1]的出现次数为0 value[1-flag][i]=0; for(int i=k;i<=max_value*k;++i)//抛出k个骰子,所有和的可能 { value[1-flag][i]=0; for(int j=1;j<=i&&j<=max_value;++j) value[1-flag][i]+=value[flag][i-j]; } flag=1-flag; } int sum=pow((double)max_value,n); for(int i=n;i<=max_value*n;++i) { double ratio=(double)value[flag][i]/sum; cout<<i<<‘ ‘<<ratio<<endl; } for(int i=0;i<max_value*n+1;++i) { delete []value[0]; delete []value[1]; } return; } int main() { Solution s; s.probality(6); s.cricile_probality(6); return 0; }
以上是关于n 个骰子的点数的主要内容,如果未能解决你的问题,请参考以下文章