题目链接:
Discovering Gold
题目描述:
有 n 堆金矿,位置为 1 - n 上,告诉你了每个位置金矿的数目 a [ i ] 。现在让你从 1 这个点开始挖金矿,下一个你要去的点通过掷骰子来决定,就是当前位置坐标+骰子数(骰子数:1 - 6),为你挖到金矿数目的期望。
解题思路:
因为起点一定要从 1 开始,所以应该倒着推才能保证从 1 这个点开始挖(最后输出的也是 dp[1])。
对于第 i 个点 ,他的期望值是: dp[i] = dp[ i + 1 ] * 1/6 + dp[ i + 2 ] * 1/6 + ··· + dp[ i + 6 ] * 1/6 + arr[ i ](当 i + 6 <= n 时),这个递推式的语义就是:我当前挖的矿,的期望是:某一堆可能能转移过来的金矿数目 乘以 某一堆可能能转移过来的概率 之和 + 当前位置的金矿数目。
需要注意的是如果当 i + 6 > n 时:
t = n - i;
dp[i] = dp[ i + 1 ] * 1 / t + dp[ i + 2 ] * 1 / t + ··· + dp[ i + t ] * 1 / t + arr[ i ];
总起来就是:
t = min(n - i, 6);
dp[i] = dp[ i + 1 ] * 1 / t + dp[ i + 2 ] * 1 / t + ··· + dp[ i + t ] * 1 / t + arr[ i ];
AC代码:
#include<bits/stdc++.h>
#define up(i, x, y) for(int i = x; i <= y; i++)
#define down(i, x, y) for(int i = x; i >= y; i--)
#define maxn ((int)1e3 + 10)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
double dp[maxn];
int arr[maxn];
int main()
{
int len = 0;
int T; scanf("%d", &T); while(T--)
{
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
int x; scanf("%d", &x);
arr[i] = x;
}
dp[n] = arr[n];
for(int i = n - 1; i >= 1; i--)
{
dp[i] = arr[i];
int x = min(n - i, 6);
for(int j = 1; j <= x; j++)
{
dp[i] += dp[i + j] / x;
}
}
printf("Case %d: %.6f\n",++len, dp[1]);
}
}