劍指offer-n骰子的點數

/*******************************************************************
Copyright(c) 2016, Tyrone Li
All rights reserved.
*******************************************************************/
// 作者:TyroneLi
//
 
/*
Q1:
    n個骰子的點數:
        把n個骰子仍在地上,所有的骰子朝上一面的點數之和爲s,輸入n,打印出
        s的所有可能的值出現的概率。
S1:
    1. 首先把n個骰子劃分爲兩堆,第一堆只有一個骰子,另外還有(n-1)堆,單獨
       的那一個有可能出現從1到6的點數可能。我們需要計算從1到6的每一種點數
       和剩下的(n-1)個骰子來計算點數之和。然後依次遞歸下去。(時間效率不高)
    2. 使用循環方法
*/

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>

int g_maxValue = 6;
void Probability(int original, int current, int sum, int*pProbabilities)
{
    if(current == 1)
    {
        pProbabilities[sum - original]++;
    }else{
        for(int i = 1; i <= g_maxValue; ++i)
        {
            Probability(original, current - 1, i + sum, pProbabilities);
        }
    }
}

void Probability(int number, int*pProbabilities)
{
    for(int i = 1; i <= g_maxValue; ++i)
        Probability(number, number, i, pProbabilities);
}

void printProbability(int number)
{
    if(number < 1)
        return;
    
    int maxSum = number * g_maxValue;
    int*pProbabilities = new int[maxSum - number + 1];
    for(int i = number; i <= maxSum; ++i)
        pProbabilities[i - number] = 0;
    
    Probability(number, pProbabilities);

    int total = pow((double)g_maxValue, number);
    double check = 0;
    for(int i = number; i <= maxSum; ++i)
    {
        double ratio = (double)pProbabilities[i - number] / total;
        check += ratio;
        std::cout << i << " " << ratio << std::endl;
    }
    std::cout << check << std::endl;
    delete[] pProbabilities;
}

void printProbability_v2(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];
    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;
    }

    int total = pow((double)g_maxValue, number);
    double check = 0;
    for(int i = number; i <= g_maxValue*number; ++i)
    {
        double ratio = (double)pProbabilities[flag][i] / total;
        check += ratio;
        std::cout << i << " " << ratio << std::endl;
    }
    std::cout << check << std::endl;
}

void test_1()
{
    std::cout << "Test 1" << std::endl;
    printProbability(10);
    printProbability_v2(10);
    std::cout << std::endl;
}

void test_printProbability()
{
    test_1();
}

int main(int argc, char**argv)
{

    test_printProbability();

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章