题意:你在一个很长很长的洞穴里。洞穴可以被表示成1 * N的长格子,每个洞穴都有一堆金子。初始的,你在1号洞穴,每一步,你可以投掷一颗6个面的骰子,如果你投掷到了编号为X的面,你就可以跳到当前位置 + X的位置,但是不能超过终点,并且能拿走这个位置的金子。求得到的金子的期望值。

分析:定义f[i]为从i到n的金币期望值,假设每个位置上的金币为g[i],那么\(f[i] = g[i] + 1 / 6 * (f[i + 1] + f[i + 2] + f[i + 3] + ... + f[i + 6])\)。注意,如果i > n - 6 + 1,那么他的🎲会受到限制,就是投的面的概率提高,为1 / (n - i),否则概率为1 / 6。然后我们可以采用记忆化搜索求出期望值。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;
const int N = 105;
int g[N], n;
double f[N];

double dfs(int u)
{
    if(f[u] >= 0) return f[u];
    //if(u == n) return 0;

    f[u] = g[u];
    int k = 0;
    for(int i = 1; i <= 6; ++i)
    {
        if(u + i <= n)
        {
            if(n - u < 6) k = n - u;
            else k = 6;
            f[u] += 1.0 / k * (dfs(u + i));
        }
    }
    return f[u];
}

int main()
{
    int t;
    scanf("%d", &t);

    int c = 0;
    while(t--)
    {

       scanf("%d", &n);

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

       memset(f, -1, sizeof f);
       double res = dfs(1);

       printf("Case %d: %.7lf\n", ++c, res);
    }

    return 0;
}