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 }

 

posted @ 2018-05-08 22:08  qrfkickit  阅读(263)  评论(0编辑  收藏  举报