Codeforces 866C Gotta Go Fast - 動態規劃 - 概率與期望 - 二分答案
You‘re trying to set the record on your favorite video game. The game consists of N levels, which must be completed sequentially in order to beat the game. You usually complete each level as fast as possible, but sometimes finish a level slower. Specifically, you will complete the i-th level in either F
Your goal is to complete all the levels sequentially in at most R total seconds. You want to minimize the expected amount of time playing before achieving that goal. If you continue and reset optimally, how much total time can you expect to spend playing?
InputThe first line of input contains integers N
Print the total expected time. Your answer must be correct within an absolute or relative error of 10 - 9.
Formally, let your answer be a, and the jury‘s answer be b. Your answer will be considered correct, if .
Examples input1 8output
2 8 81
3.14input
2 30output
20 30 80
3 9 85
31.4input
4 319output
63 79 89
79 97 91
75 87 88
75 90 83
314.159265358Note
In the first example, you never need to reset. There‘s an 81% chance of completing the level in 2 seconds and a 19% chance of needing 8 seconds, both of which are within the goal time. The expected time is 0.81·2 + 0.19·8 = 3.14.
In the second example, you should reset after the first level if you complete it slowly. On average it will take 0.25 slow attempts before your first fast attempt. Then it doesn‘t matter whether you complete the second level fast or slow. The expected time is 0.25·30 + 20 + 0.85·3 + 0.15·9 = 31.4.
題目大意 一個人打遊戲,需要不超過$R$秒通過$n$關,第$i$關有$P_{i}$的概率用$F_{i}$秒通過,$\left(1 - P_{i}\right)$的概率用$S_{i}$通過($F_{i} < S_{i}$),通過每一關可以選擇重置遊戲,然後從頭開始,或者去打下一關。問不超過$R$秒通過所有關卡的期望耗時。
轉移是顯然的。(如果這個都不會,請自定百度“概率dp入門題”)
然後發現轉移有環,還要做決策?
然後列方程吧。。開心地發現不會解。
可惜這裏是信息學競賽,不是數學競賽。由於轉移都需要 dp[0][0] 但是開始不知道它,所以考慮二分它,然後和推出來的 dp[0][0] 作比較。
經過各種瞎猜和亂搞,可以發現一個神奇的事情
然後就可根據它來確定一次check後,二分的範圍。
另外,由於坑人的精度問題,所以最好不要寫while (l + eps < r) ,總之我這麽寫各種因為精度問題的TLE來了。
Code
1 /** 2 * Codeforces 3 * Problem#866C 4 * Accepted 5 * Time: 62ms 6 * Memory: 4316k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 const long double eps = 1e-9; 13 const int binary_lim = 80; 14 15 int n, R; 16 int *fs, *ss; 17 double *ps; 18 19 inline void init() { 20 scanf("%d%d", &n, &R); 21 fs = new int[(n + 1)]; 22 ss = new int[(n + 1)]; 23 ps = new double[(n + 1)]; 24 for(int i = 1; i <= n; i++) { 25 scanf("%d%d", fs + i, ss + i); 26 cin >> ps[i]; 27 ps[i] *= 0.01; 28 } 29 } 30 31 boolean vis[51][5105]; 32 double f[51][5105]; 33 34 double dfs(int d, int t, double &mid) { 35 if(d == n) return (t > R) ? (mid) : (0); 36 if(vis[d][t]) return f[d][t]; 37 vis[d][t] = true; 38 f[d][t] = (dfs(d + 1, t + fs[d + 1], mid) + fs[d + 1]) * ps[d + 1] + (dfs(d + 1, t + ss[d + 1], mid) + ss[d + 1]) * (1 - ps[d + 1]); 39 if(mid < f[d][t]) f[d][t] = mid; 40 return f[d][t]; 41 } 42 43 double dp(double mid) { 44 memset(vis, false, sizeof(vis)); 45 return dfs(0, 0, mid); 46 } 47 48 inline void solve() { 49 double l = 0, r = 1e9; 50 for(int i = 0; i < binary_lim; i++) { 51 double mid = (l + r) / 2; 52 if(dp(mid) < mid) r = mid; 53 else l = mid; 54 } 55 printf("%.9lf", l); 56 } 57 58 int main() { 59 init(); 60 solve(); 61 return 0; 62 }
Codeforces 866C Gotta Go Fast - 動態規劃 - 概率與期望 - 二分答案