JZ-C-43
剑指offer第四十三题:n个骰子的点数:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s,求所有可能的s的概率
1 //============================================================================ 2 // Name : JZ-C-43.cpp 3 // Author : Laughing_Lz 4 // Version : 5 // Copyright : All Right Reserved 6 // Description : n个骰子的点数:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s,求所有可能的s的概率 7 //============================================================================ 8 9 #include <iostream> 10 #include <math.h> 11 #include <stdio.h> 12 using namespace std; 13 14 int g_maxValue = 6; //骰子面数 15 16 // ====================方法一==================== 17 void Probability(int number, int* pProbabilities); 18 void Probability(int original, int current, int sum, int* pProbabilities); 19 /** 20 * 递归:许多计算时重复的,当number变大时,性能很低 21 */ 22 void PrintProbability_Solution1(int number) { 23 if (number < 1) 24 return; 25 26 int maxSum = number * g_maxValue; 27 int* pProbabilities = new int[maxSum - number + 1]; 28 for (int i = number; i <= maxSum; ++i) 29 pProbabilities[i - number] = 0; 30 31 Probability(number, pProbabilities); 32 33 int total = pow((double) g_maxValue, number);//pow(x,y)函数:表示x^y 34 for (int i = number; i <= maxSum; ++i) { 35 double ratio = (double) pProbabilities[i - number] / total; 36 printf("%d: %e\n", i, ratio); 37 } 38 39 delete[] pProbabilities; 40 } 41 42 void Probability(int number, int* pProbabilities) { 43 for (int i = 1; i <= g_maxValue; ++i) 44 Probability(number, number, i, pProbabilities); 45 } 46 47 void Probability(int original, int current, int sum, int* pProbabilities) { 48 if (current == 1) { 49 pProbabilities[sum - original]++; 50 } else { 51 for (int i = 1; i <= g_maxValue; ++i) { 52 Probability(original, current - 1, i + sum, pProbabilities); 53 } 54 } 55 } 56 57 // ====================方法二==================== 58 /** 59 * 循环:利用两个数组交替存储两次循环后各值可能出现的次数。时间性能好 60 */ 61 void PrintProbability_Solution2(int number) { 62 if (number < 1) 63 return; 64 65 int* pProbabilities[2]; 66 pProbabilities[0] = new int[g_maxValue * number + 1]; 67 pProbabilities[1] = new int[g_maxValue * number + 1]; 68 for (int i = 0; i < g_maxValue * number + 1; ++i) { 69 pProbabilities[0][i] = 0; 70 pProbabilities[1][i] = 0; 71 } 72 73 int flag = 0; 74 for (int i = 1; i <= g_maxValue; ++i) 75 pProbabilities[flag][i] = 1;//第一次,先将各值可能出现的次数赋为1 76 77 for (int k = 2; k <= number; ++k) {//number 骰子数 78 for (int i = 0; i < k; ++i) 79 pProbabilities[1 - flag][i] = 0; 80 81 for (int i = k; i <= g_maxValue * k; ++i) { 82 pProbabilities[1 - flag][i] = 0;//先重新赋值为0 ★★(结合flag交替使用得知:这里每一轮都会重复计算上一轮得过的次数,因为每次都是从值为0开始。所以仍有重复计算的问题) 83 for (int j = 1; j <= i && j <= g_maxValue; ++j) 84 pProbabilities[1 - flag][i] += pProbabilities[flag][i - j];//★★★这里表示f(n)=f(n-1)+f(n-2)+f(n-3)+f(n-4)+f(n-5)+f(n-6) 85 } 86 87 flag = 1 - flag;//交替使用两个数组 88 } 89 90 double total = pow((double) g_maxValue, number); 91 for (int i = number; i <= g_maxValue * number; ++i) { 92 double ratio = (double) pProbabilities[flag][i] / total; 93 printf("%d: %e\n", i, ratio); 94 } 95 96 delete[] pProbabilities[0]; 97 delete[] pProbabilities[1]; 98 } 99 100 // ====================测试代码==================== 101 void Test(int n) { 102 printf("Test for %d begins:\n", n); 103 104 printf("Test for solution1\n"); 105 PrintProbability_Solution1(n); 106 107 printf("Test for solution2\n"); 108 PrintProbability_Solution2(n); 109 110 printf("\n"); 111 } 112 113 int main(int argc, char** argv) { 114 Test(1); 115 Test(2); 116 Test(3); 117 Test(4); 118 Test(11); 119 Test(0); 120 121 return 0; 122 }
—————————————————————————————————————行走在人猿的并行线——Laughing_Lz