1. 程式人生 > 實用技巧 >面試題60:n個骰子的點數

面試題60:n個骰子的點數

  可以很輕鬆地想到用回溯法進行暴力列舉,但複雜度很高O(6^n),肯定會超時,所以可以類比為斐波那契數列的形式:\(f(n) = f(n-1)+f(n-2)+f(n-3)+f(n-4)+f(n-5)+f(n-6)\)。採用類似動態規劃的方法(其實和斐波那契一樣,並不嚴格是動態規劃)。

回溯法暴力列舉C++

int g_maxValue = 6;

// 暴力遞迴,複雜度很高O(6^n),絕對超時
void Probability(int original, int current, int sum, int* pProbabilities){
    if(current == 0){
        pProbabilities[sum - original]++;
        return ;
    }

    for(int i = 1; i <= g_maxValue; ++i)
        Probability(original, current - 1, i + sum, pProbabilities);
}


void PrintProbability_Solution1(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, number, 0, pProbabilities);

    int total = pow((double)g_maxValue, number);
    for(int i = number; i <= maxSum; ++i){
        double ratio = (double)pProbabilities[i - number] / total;
        printf("%d: %e\n", i, ratio);
    }

    delete[] pProbabilities;
}


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

    PrintProbability_Solution1(6);

    return 0;
}