POJ Problem 3941 Expected Allowance

現有n個m面的骰子,Ujisato要擲這些骰子,他所獲得的鈔票數是這些骰子的點數之和減去k。而且即使點數之和小於k,Ujisato也能得到一張鈔票。假設骰子的每一面的點數爲1到m,投得每一面的概率是相等的。

動態規劃思想:

設dp[i%2][j]表示投第i(0<=i<n)個骰子時,骰子點數之和爲j總共有多少種情況。

#include<iostream>
#include<vector>
#include<math.h>
#include<stdio.h>
using namespace std;
int main(){
    int n, m, k;
    while(cin >> n >> m >> k){
        if(n == 0 && m == 0 && k == 0)
            break;
        vector<vector<int> > dp(2);
        dp[0].resize(n*m+1);
        dp[1].resize(n*m+1);
        dp[0][0] = 0;
        for(int i = 1; i <= m; ++i)
            dp[0][i] = 1;
        for(int i = m+1; i <= n*m; ++i)
            dp[0][i] = 0;
        for(int i = 1; i < n; ++i){
            for(int j = 0; j <= n*m; ++j)
                dp[i%2][j] = 0;
            for(int p = 1; p <= n*m; ++p)
                for(int j = 1; j <= m && j < p; ++j)
                    dp[i%2][p] += dp[1-i%2][p-j];
        }
        int sum = 0;
        for(int i = 1; i <=k ; ++i)
            sum += dp[(n-1)%2][i];
        for(int i = k+1; i <= n*m; ++i)
            sum += (i-k)*dp[(n-1)%2][i];
        int total = pow(1.0*m, 1.0*n);
        double ans = (double)(1.0*sum)/total;
        printf("%.8f\n", ans);
    }
    return 0;
}


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