题意
有一排洞穴,你在第一个洞穴,可以获得该洞穴的黄金,然后掷标有1-6的骰子,
是几就往下走几步,并得到该洞穴的黄金。
当离终点小于6步且不合法时就重掷直到合法为止。
求起点出发的黄金的期望。
题解
概率dp入门题。
考虑到自己dp比较菜,概率dp更菜,就做一个总结一个吧。
就是你在这点的期望,等于这个点的黄金数,加上你能走到所有的所有合法点的期望的平均。
那我能走到的所有合法点期望怎么求?
显然是从后往前dp,或者递归搜索。
代码
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <bitset>
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int>
#define si set<int>
#define pii pair<int,int>
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
double dp[105];//dp[i]表示从i点出发到n点的期望
int main()
{
int t;
sci(t);
rep(k,1,t)
{
mem(dp,0);
int n;
sci(n);
rep(i,0,n-1)scanf("%lf",&dp[i]);
per(i,n-2,0)
{
int step=min(6,(n-1-i));//step为可以向前走的步数的最大值
rep(j,1,step)//j为实际往前走的步数
{
dp[i]+=dp[i+j]/step;//有1/6的概率走到i+step获得i+step的期望
//注意如果step<6比如说step=4,这里会重复投骰子直至合法,故走到以后四个点的概率均为1/4
//用回溯的方法 将未来没有走到的点的期望都累加到前面的点上
}
}
printf("Case %d: %.7lf\n",k,dp[0]);
}
return 0;
}