题意:你在一个很长很长的洞穴里。洞穴可以被表示成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;
}