zoj-3604 Help Me Escape[概率dp]

题目意思: 一个吸血鬼,每天有n条路走,
每次随机选一条路走,每条路有限制,
如果当这个吸血鬼的能力大于某个值c[i],
那么只需要花费ti(ti = (1.0 + sqrt(5.0))/2 * c[i] * c[i])
天的时间就可以逃出去,否则,花费1天的时间,
吸血鬼的能力增加c[i],花费1天的时间,然后继续下一天的尝试。

求逃出去的期望。

被这道题的四舍五入坑惨了。

令E(f)表示吸血鬼在战斗力为f的时候逃出去的期望。

对于走每条路 i,概率为1/n有两种考虑

(1)f>c[i],此时吸血鬼可以从这条路逃走 E(f)+=t[i]*(1/n);

(2)f<=c[i],此时吸血鬼得继续下一天的尝试,E(f+c[i])+=(E(f)+1)*(1/n);这里得将公式逆推刚好也是E(f)+=(1+E(f+c[i]))*(1/n);

所以E(f)=∑{t[i]*(1/n)}+∑{(E(j+c[j])+1)*(1/n)}            i表示f>c[i]的路,j表示f<=c[i]的路

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=10008;
const double eps=1E-8;
const double ft=(1.0 + sqrt(5.0))/2.0;
int n;
int c[maxn];
double t[maxn],E[maxn*4];
double DP(int f)
{ 	
	double &res=E[f];
	if(res>eps) return res;
	for(int i=1;i<=n;++i)
	{
		if(f>c[i])	res+=int(t[i])*1.0/n;
		else res+=(1+DP(f+c[i]))*1.0/n;
	}
	return res;
}
void init()
{
	memset(E,0,sizeof(E)); 
	t[0]=0;
	for(int i=1;i<=n;++i)
	{
		t[i]=ft* c[i] * c[i];
	}
}
int main()
{
	int f;
	while(~scanf("%d%d",&n,&f))
	{
		for(int i=1;i<=n;++i)
			scanf("%d",c+i);
		init();
		printf("%.3lf\n",DP(f));
	}
	return 0;
}


你可能感兴趣的:(acm_dp)