n个骰子的点数44

来源:互联网 发布:crf算法 编辑:程序博客网 时间:2024/05/17 23:05

抽象建模的能力

  1. 建模的第一步是选择合理的数据结构来表述问题。即建立模型。
  2. 建模的第二步是分析模型中的内在规律,并用编程语言表示这种规律。
  3. 我们只有对现实问题进行深入细致的观察分析之后,才能找到模型中的规律,才有可能编程解决问题。

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

解题思路:

  1. n个骰子的点数和的最小值为n,最大值为6n;
  2. n个骰子的所有点数的排列为6n;
  3. 先统计每一个点数出现的次数,然后把每一个点数出现的次数除以6^n,就能求出每个点出现的概率。

解法一:基于递归求骰子点数,时间效率不够高

//解法一,递归void RecursiveProbability(int original, int current, int sum, int *pProbabilities){    if(current == 1)        pProbabilities[sum - original]++;    else{        for(int i = 1; i <= g_maxValue; ++i)            RecursiveProbability(original, current - 1, i + sum, pProbabilities);    }}void RecursiveProbability(int number, int *pProbabilities){    for(int i = 1; i <= g_maxValue; ++i)        RecursiveProbability(number, number, i, pProbabilities);}void PrintRecursiveProbability(int number){    if(number < 1)        return;    //最大和    int maxSum = number *g_maxValue;    //保存概率的数组    int *pProbabilities = new int[maxSum - number + 1];    //初始化为0次    for(int i = number; i <= maxSum; ++i)        pProbabilities[i-number] = 0;    //先统计每一个点数出现的次数,    RecursiveProbability(number, pProbabilities);    int total = pow((double)g_maxValue, number);    for(int i = number; i <= maxSum; ++i){        //然后把每一个点数出现的次数除以6^n,就能求出每个点出现的概率        double ratio = (double)pProbabilities[ i - number] / total;        printf("%d: %e\n", i, ratio);    }    delete []pProbabilities;}

解法二:基于循环求骰子点数,时间性能好

//解法二,循环,时间性能好void PrintLoopProbability(int number){    if(number < 1)        return;    //用两个数组来存储骰子点数的每一个总数出现的次数    int *pProbabilities[2];    pProbabilities[0] = new int[g_maxValue * number + 1];    pProbabilities[1] = new int[g_maxValue * number + 1];    //全部初始化为0    for(int i = 0; i < g_maxValue * number + 1; ++i){        pProbabilities[0][i] = 0;        pProbabilities[1][i] = 0;    }    int flag = 0;    for(int i = 1; i <= g_maxValue; ++i)        pProbabilities[flag][i] = 1;    for(int k = 2; k <= number; ++k){        for(int i = 0; i < k; ++ i)            pProbabilities[1 - flag][i] = 0;        for(int i = k; i <= g_maxValue * k; ++i){            pProbabilities[1 - flag][i] = 0;            for(int j = 1; j <= i && j <= g_maxValue; ++j)                pProbabilities[1 - flag][i] += pProbabilities[flag][i - j];        }        flag = 1 - flag;    }    double total = pow((double)g_maxValue, number);    for(int i = number; i <= g_maxValue * number; ++i){        //然后把每一个点数出现的次数除以6^n,就能求出每个点出现的概率        double ratio = (double)pProbabilities[flag][i] / total;        printf("%d: %e\n", i, ratio);    }    delete []pProbabilities[0];    delete []pProbabilities[1]; }

测试用例:

//测试用例int main(){    //解法一,递归    PrintRecursiveProbability(6);    std::cout << std::endl;    //解法二,循环    PrintLoopProbability(6);    return 0;}
0 0
原创粉丝点击