题目:把n个骰子扔在地上 所有骰子朝上一面的点数之和为s 输入n 打印出s的所有可能出现的概率
思路:将n个骰子分为两堆 第一堆只有一个 另一个有n-1个 单独的那一个有6中可能 需要计算从1到6的每一种点数 和剩下的n-1个
骰子 来计算点数 和 接下来把剩下的n-1个骰子还是分成两堆 第一堆只有一个 第二堆有n-2个 把上一轮单独骰子的点数和这一轮单独骰子点数相加 再和剩下的n-2个
骰子来计算点数和 递归的计算 直到只剩下一个骰子
定义一个长度为6n-n+1的数组 和为s的点数出现的次数保存到数组第s-n个元素中
void probabilitys(int original, int current, int sum, int *A)
{
if (current == 1)
{
A[sum]++;
}
else
{
for (int i = 1;i <= 6;i++)
{
probabilitys(original, current - 1, i+sum, A);
}
}
}
void probability(int number, int *A)
{
for (int i = 1;i <= 6;i++)
{
probabilitys(number, number, i, A);
}
}
void printprobability(int number, int *A)
{
if (number < 1)
return;
int total = pow( 6,n);
probability(number, A);
for (int i = n;i <= 6*n;i++)
{
cout << i << ' ' <<A[i]<<' '<< double(double(A[i]) / total) << endl;
}
}
递归求解会导致很多重复计算 可以考虑用两个数组存储骰子点数的每一个总数出现的次数
在一次循环中第一个数组中的第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之和
void printprobability2(int number)
{
int flag = 0;
int *A[2];
A[0] = new int[6 * number + 1];
A[1] = new int[6 * number + 1];
memset(A[0], 0, sizeof(int)*(6 * n + 1));
memset(A[1], 0, sizeof(int)*(6 * n + 1));
for (int i = 1;i <= 6;i++)
A[0][i] = 1;
for (int k = 2;k <= number;k++)
{
for (int i = 0;i < k;i++)
A[1 - flag][i] = 0;
for (int i = k;i <= k * 6;i++)
{
A[1 - flag][i] = 0;
for (int j = 1;j <= i && j <= 6;j++)
A[1 - flag][i] += A[flag][i - j];
}
flag = 1 - flag;
}
int total = pow(6, number);
for (int i = n;i <= 6 * n;i++)
{
cout << i << ' ' << A[flag][i] << ' ' << double(double(A[flag][i]) / total) << endl;
}
}
481

被折叠的 条评论
为什么被折叠?



