题目意思: 一个吸血鬼,每天有n条路走,每次随机选一条路走,每条路有限制,如果当这个吸血鬼的能力大于某个值c[i],那么只需要花费ti(ti = (1.0 + sqrt(5.0))/2 * c[i] * c[i]) 天的时间就可以逃出去,否则,花费1天的时间,吸血鬼的能力增加c[i],花费1天的时间,然后继续下一天的尝试。求逃出去的期望。设dp[v] ,表示当能力值为v的时的期望。所以方程很容易写了,dp[v] = sum{ ti/n } + sum { (1 + dp[v + c[i]])/n } ;对于路i,如果v大于路i的限制,那么就能够用ti逃出去,概率为{1/n}否则只能进入下一天的尝试,所以需要用的时间为dp[v + c[i]] + 1 ,概率为{1/n}; 直接使用记忆化搜索的方式写。
/*
author : csuchenan
prog : zoj3640
algorithm : probability DP
Accepted 3640 C++ 1270 1744 chenan
*/
#include <cstdio>
#include <cstring>
#include <cmath>
const int maxn = 200010 ;
int c[110] ;
double dp[maxn] ;
int n , f ;
double dfs(int v){
if(dp[v] > 0)
return dp[v] ;
dp[v] = 0 ;
for(int i = 0 ; i < n ; i ++){
//直接从f点逃出去
if(v > c[i]){
double temp = (1.0 + sqrt(5.0))/2 * c[i] * c[i] ;
int t = (int) temp ;
dp[v] += t * 1.0 / n ;
}
else{
dp[v] += (1 + dfs(v + c[i]))/n ;
}
}
return dp[v] ;
}
int main(){
freopen("test.in" ,"r" , stdin);
while(scanf("%d%d" , &n , &f) != EOF){
for(int i = 0 ; i < n ; i ++)
scanf("%d" , &c[i]) ;
memset(dp , 0 , sizeof(dp)) ;
dfs(f) ;
printf("%.3f\n" , dp[f]) ;
}
return 0 ;
}