LightOj 1030

题目链接:http://lightoj.com/volume_showproblem.php?problem=1030

题意:在一个1*n 的格子里,每个格子都有相应的金币数,走到相应格子的话,就会得到该格子的金币。 

现在有一个人在1这个位置,手里有一颗骰子,骰子摇到几,他就前进几步,但如果当前位置+骰子数 > n,那么他就会重新摇色子一直到<=n为止。 
走到n这个位置的话,意味着游戏结束了。
 问游戏结束时,这个人得到金币的期望。

设dp[i]表示从i号格子出去的期望,所以dp[i]是和i后面的紧接着6个数有关, 那么 则有dp[i] = (dp[i+1]/6 + ... + dp[i+6]/6) + dp[i]。

初始化dp[i] = 第i个格子的gold值。
 
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
#define N 105
#define met(a, b) memset(a, b, sizeof(a))

typedef long long LL;

int main()
{
    int T, t = 1, n;
    scanf("%d", &T);
    while(T--)
    {
        double dp[N];
        int a[N];
        met(dp, 0);

        scanf("%d", &n);
        for(int i=1; i<=n; i++)
            scanf("%d", &a[i]);

        dp[n] = a[n];

        for(int i=n-1; i>=1; i--)
        {
            dp[i] = a[i];
            int k = min(6, n-i);
            for(int j=1; j<=k; j++)
                dp[i] += dp[i+j]/k;
        }

        printf("Case %d: %.6f
", t++, dp[1]);
    }
    return 0;
}
View Code
 
还有就是可以先求出到达每个格子的概率dp[i],然后再乘上格子的金币数就是所求期望了;
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
#define N 105
#define met(a, b) memset(a, b, sizeof(a))

typedef long long LL;

int main()
{
    int T, t = 1, n;
    scanf("%d", &T);
    while(T--)
    {
        double dp[N];
        int a[N];
        met(dp, 0);

        scanf("%d", &n);
        for(int i=1; i<=n; i++)
            scanf("%d", &a[i]);

        dp[1] = 1.0;

        for(int i=1; i<=n; i++)
        {
            int k = min(6, n-i);
            for(int j=1; j<=k; j++)
                dp[i+j] += dp[i]/k;
        }
        double ans = 0;
        for(int i=1; i<=n; i++)
            ans += a[i]*dp[i];
        printf("Case %d: %.6f
", t++, ans);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5754909.html