题意:一个人在一个有N条道路的地方,每天他会被随机传送到任意一条道路,每个道路有一个危险值ci,他有个战斗力f,如果f>ci,那么在战斗ti天后会出去,否则f会增加ci,第二天继续这个过程,问他出去的天数的期望。
思路:比较简单的概率dp吧,dp[x]表示战斗力为x时出去的天数的期望。如果x>max{ci},那么天数的期望就为1/n*Σti,否则,dp[x]=1/n*Σti(x>ci)+1/n*Σ(1+dp[x+ci])。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=10000+100;
double dp[maxn],p;
bool flag[maxn];
int c[maxn],t[maxn],maxc,n;
inline int cal(int v)
{
return floor((1.0+sqrt(5.0))/2.0*v*v);
}
double f(int x)
{
if(x>maxc)
{
double res=0;
for(int i=1;i<=n;++i)
res+=p*t[i];
return res;
}
if(flag[x]) return dp[x];
flag[x]=true;
dp[x]=0;
for(int i=1;i<=n;++i)
{
if(x>c[i]) dp[x]+=p*t[i];
else dp[x]+=p*(1+f(x+c[i]));
}
return dp[x];
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int v;
while(~scanf("%d%d",&n,&v))
{
memset(flag,0,sizeof(flag));
maxc=-1;
for(int i=1;i<=n;++i)
{
scanf("%d",&c[i]);
maxc=max(maxc,c[i]);
t[i]=cal(c[i]);
}
p=1.0/n;
double ans=f(v);
printf("%.3lf\n",ans);
}
return 0;
}