zoj 3640 Help Me Escape
题意:
给出n条路和每条路的困难度ci。一个人初始的能力值为f
这个人每天被随机传送到一条路,如果他的能力值f大于ci,那么它就可以花费ti的时间逃出去,ti与ci的关系是给出的函数关系。
如果他的能力值小于等于ci,那么他的能力值就会增加ci,并且等待第二天再次传送。
问逃出去的期望的天数。
思路:
求期望的概率dp,逆推。
一开始用dp[i][j]表示在i条路上,能力值为j时的期望,但是t了,中间应该多了许多重复计算的状态。。。。
假设dp[i]表示能力值为i时逃出去的期望,那么当i大于ci中的最大时,逃出去的天数显然就是总天数的平均值。
dp[i] = (Σt[j] + Σdp[i+c[k]]) / n,(i > c[j],i <= c[k])。
注意逆推,然后i的初始值时从ci的最大值开始的。
我觉得循环比记忆化搜索好写,而且对我来说更易理解。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <math.h> 5 using namespace std; 6 const int N = 105; 7 double dp[20005]; 8 int c[N],t[N]; 9 int main() 10 { 11 int n,f; 12 while (scanf("%d%d",&n,&f) != EOF) 13 { 14 memset(dp,0,sizeof(dp)); 15 int mx = 0; 16 for (int i = 1;i <= n;i++) 17 { 18 scanf("%d",&c[i]); 19 mx = max(mx,c[i]); 20 } 21 double sum = 0; 22 for (int i = 1;i <= n;i++) 23 { 24 t[i] = (int) (floor(((1.0+sqrt(5.0)) / 2) * c[i] * c[i])); 25 sum += t[i]; 26 } 27 sum /= n; 28 for (int i = mx + 1;i <= 20000;i++) dp[i] = sum; 29 for (int i = mx;i >= f;i--) 30 { 31 for (int j = 1;j <= n;j++) 32 { 33 if (i > c[j]) dp[i] += t[j]; 34 else dp[i] += dp[i+c[j]] + 1; 35 } 36 dp[i] /= n; 37 } 38 printf("%.3f\n",dp[f]); 39 } 40 return 0; 41 }
康复训练中~欢迎交流!