1. 程式人生 > >九度 題目1255:骰子點數概率

九度 題目1255:骰子點數概率

題目描述:

把n個骰子扔在地上,所有骰子朝上一面的點數之和為S。輸入n,打印出S的所有可能的值出現的概率。

輸入:

輸入包括一個整數N(1<=N<=1000),代表有N個骰子。

輸出:

可能有多組測試資料,對於每組資料,
按照Sample Output的格式輸出每一個可能出現的和S的概率。

樣例輸入:
1
2
樣例輸出:
1: 0.167
2: 0.167
3: 0.167
4: 0.167
5: 0.167
6: 0.167

2: 0.028
3: 0.056
4: 0.083
5: 0.111
6: 0.139
7: 0.167
8: 0.139
9: 0.111
10: 0.083
11: 0.056

12: 0.028

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

一開始想到的是用概率公式去推。。。。。後來借鑑了大神們的做法,原來是用dp敲打

因為如果現在是第K個骰子,當前結果n由第k-1個的結果n-1,n-2, n-3,n-4, n-5, n-6分別加1,2,3,4,5,6得出,事實上只需要保持二組資料:當前的結果和前一個骰子的結果。這裡用位與運算,用最後一位的奇偶性來區別。

#include<iostream>
#include<string.h>
#include<iomanip>
#include<stdio.h>
using namespace std;
double ap[2][6003];
double a6[1003];
int main()
{
    int i;
    a6[0]=1;
    for(i=1;i<1001;i++)
        a6[i]=6*a6[i-1];    
    int n;
    while(cin>>n)
    {
        memset(ap,0,sizeof(ap));
        int j,k;
        ap[1][1]=1;
        ap[1][2]=1;
        ap[1][3]=1;
        ap[1][4]=1;
        ap[1][5]=1;
        ap[1][6]=1;
        for(j=2;j<=n;j++)
        {
            for(k=j;k<=6*j;k++)
            {   
                ap[j&1][k]=0;           
                for(i=1;k-i>0&&i<=6;i++)
                {
                    ap[j&1][k]+=ap[(j+1)&1][k-i];
                }
            }
        }
        for(i=n;i<=n*6;i++)
            printf("%d: %.3lf\n",i,ap[n&1][i]/a6[n]);
                  printf("\n");
    }
}
/**************************************************************
    Problem: 1255
    User: 午夜小白龍
    Language: C++
    Result: Accepted
    Time:250 ms
    Memory:1620 kb
****************************************************************/