//把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能
//的值出现的概率。
#include "stdio.h"
#include "cmath"
#include "helper.h"
using namespace std;
//方法1:递归思路。把骰子分成两堆,一堆1个,另一堆n-1个。
int diceSurface = 6;
void probabilityRecursively(int current, int sum,
int* appearanceCount)
{
if (current == 1)
appearanceCount[sum]++;
else
{
for (int i = 1; i <= diceSurface; ++i)
probabilityRecursively(current - 1, i + sum, appearanceCount);
}
}
void probability(int* appearanceCount, int n)
{
for (int i = 1; i <= diceSurface; ++i)
probabilityRecursively(n, i, appearanceCount);
}
void printAllProbability0(int n)
{
if (n < 1)
return;
int maxSum = n * diceSurface;
int* appearanceCount = new int[maxSum + 1]; //不会初始化为0
for (int i = 0; i <= maxSum; i++)
appearanceCount[i] = 0; //初始化
probability(appearanceCount, n);
int totalProbability = pow(diceSurface, n);
for (int i = n; i <= maxSum; i++)
printf("P(%d): %d/%d\n", i, appearanceCount[i], totalProbability);
delete[] appearanceCount;
}
//两个数组交替进行,有点类似动态规划的意思。
void printAllProbability1(int n)
{
if (n < 1)
return;
int maxSum = n * diceSurface;
int* appearanceCount[2];
appearanceCount[0] = new int[maxSum + 1];
appearanceCount[1] = new int[maxSum + 1];
for (int i = 0; i <= maxSum; ++i)
{
appearanceCount[0][i] = 0;
appearanceCount[1][i] = 0;
}
int flag = 0;
for (int i = 1; i <= diceSurface; i++)
appearanceCount[flag][i] = 1;
for (int k = 2; k <= n; ++k)
{
for (int i = 0; i < k; ++i)
appearanceCount[1 - flag][i] = 0;
for (int i = k; i <= maxSum; ++i)
{
appearanceCount[1 - flag][i] = 0;
for (int j = 1; j <= i && j <= diceSurface; ++j)
appearanceCount[1 - flag][i] += appearanceCount[flag][i - j];
}
flag = 1 - flag;
}
int totalProbability = pow(diceSurface, n);
for (int i = n; i <= maxSum; i++)
printf("P(%d): %d/%d\n", i, appearanceCount[flag][i], totalProbability);
delete[] appearanceCount[0];
delete[] appearanceCount[1];
}
int main()
{
int n = 3;
printAllProbability1(n);
return 0;
}
这道题很棒!