1. 程式人生 > 實用技巧 >Help Me Escape ZOJ - 3640

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;
}