掷骰子,求得每个数的概率


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

 

先分析思路,再看实现。

 

首先解决前提性的问题:一个骰子的点数只可能是[1,6],所以S的值的取值范围是[n,6n],这里当然只考虑整数。

 

思路一:统计各个S值出现的次数,然后

 

      各个S值出现的概率 = 各个S值出现的次数 / n个骰子所有点数的排列数

 

 

其中,n个骰子所有点数的排列数等于6n,而各个S值出现的次数就需要建立一个数组来进行统计。这时,问题就变成怎样来求各个S出现的次数了。方法我直接引用原文的文字如下:

 

 

==========================  以下文字引用自原文 ============================

 

分析:玩过麻将的都知道,骰子一共6个面,每个面上都有一个点数,对应的数字是1到 6之间的一个数字。所以,n个骰子的点数和的最小值为n,最大值为6n。因此,一个直观的思路就是定义一个长度为6n-n的数组,和为S的点数出现的次数保存到数组第S-n个元素里。另外,我们还知道n个骰子的所有点数的排列数6^n。一旦我们统计出每一点数出现的次数之后,因此只要把每一点数出现的次数除以6^n,就得到了对应的概率。

该思路的关键就是统计每一点数出现的次数。要求出n个骰子的点数和,我们可以先把n个骰子分为两堆:第一堆只有一个,另一个有n-1个。单独的那一个有可能出现从1到6的点数。我们需要计算从1到6的每一种点数和剩下的n-1个骰子来计算点数和。接下来把剩下的n-1个骰子还是分成两堆,第一堆只有一个,第二堆有n-2个。我们把上一轮那个单独骰子的点数和这一轮单独骰子的点数相加,再和剩下的n-2个骰子来计算点数和。分析到这里,我们不难发现,这是一种递归的思路。递归结束的条件就是最后只剩下一个骰子了。

 

==========================  以上文字引用自原文 ============================

int g_max=6;
int g_number=6;
void compute_probably(int orignal,int current,int value,int tempsum,int* pProbably)
{
	if(1==current)
	{
		int sum=tempsum+value;
		pProbably[sum-orignal]++;
	}
	else
	{
		for(int i=1;i<=g_max;i++)
		{
			int sum=tempsum+value;
			compute_probably(orignal,current-1,i,sum,pProbably);
		}
	}
}
int main()
{
	//我们求得在6个骰子中所有点数出现的概率
	int sum=g_max*g_number;
	int *pProbably=new int[sum-g_number+1];
	memset(pProbably,0,(sum-g_number+1)*sizeof(int));
	for(int i=1;i<=g_max;i++)
	{
		compute_probably(g_number,g_number,i,0,pProbably);
	}
	double total=pow((double)g_max,g_number);
	double m=0.0;
	for(int i=0;i<sum-g_number+1;i++)
	{

		double tmp=(pProbably[i])/total;
		m+=tmp;
		cout<<"点数是:"<<i+g_number<<" 概率是:"<<tmp<<endl;
	}
	cout<<"和是:"<<m<<endl;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值