Help Me Escape ZOJ - 3640
题意
该隐被困在有\(n\)条路的山洞里,每条路有一个困难值\(c_i\),每条路通过的时间\(t_i = \lfloor \frac{1 + \sqrt{5}}{2} * c_i ^ 2\rfloor\)天
每天该隐都会被传送到任意一条路,如果他的战斗力\(f > c_i\),他就能通过该路,否则不能。
没能通过的路会将该隐的战斗力增加\(c_i\)
给定\(n\)条路的\(c_i\),给定\(n\)和初始战斗力\(f\),求该隐逃离山洞的期望天数。
分析
考虑DP
是否可以对天数DP?显然我们需要同时记录天数和战斗力,这是二维的DP,并且每一维都是
1w级别的,不行。
然后我们发现天数不重要,战斗力比较重要,我们考虑\(dp[i]\)表示战斗力为\(i\)所期望逃脱的天数,
\(Ans = dp[f]\)
\[dp[j] = \frac {\sum_{i = 1}^{n} t_i*[j>c_i] \sum_{i=1}^{n}dp[j + c_i]*[j \leq c_i]}{n}
\]
\(j + c_i\)的范围在2w以内。
记忆化\(dfs\)和\(dp\)都可以。
[code]
#include<bits/stdc++.h>
using namespace std;
#define ld long double
ld dp[20050];
int n,f,c[110],t[110];
int main(){
while(scanf("%d%d",&n,&f) != EOF){
for(int i = 1; i <= n; ++ i) { scanf("%d",&c[i]); t[i] = ((1.0 + sqrt(5.0)) / 2.0 * c[i] * c[i]); }
for(int i = 20010; i >= f; -- i){
dp[i] = 0;
for(int j = 1; j <= n; ++ j)
if(i > c[j]) dp[i] += t[j];
else dp[i] += (1 + dp[i + c[j]]);
dp[i] /= n;
}
printf("%.3Lf\n",dp[f]);
}
return 0;
}