Codeforces 866C Gotta Go Fast - 动态规划 - 概率与期望 - 二分答案

Posted yyf0309

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 Fi seconds or Si seconds, where Fi < Si, and there‘s a Pi percent chance of completing it in Fi seconds. After completing a level, you may decide to either continue the game and play the next level, or reset the game and start again from the first level. Both the decision and the action are instant.

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?

Input

The first line of input contains integers N and R 技术分享图片, the number of levels and number of seconds you want to complete the game in, respectively. N lines follow. The ith such line contains integers Fi, Si, Pi (1 ≤ Fi < Si ≤ 100, 80 ≤ Pi ≤ 99), the fast time for level i, the slow time for level i, and the probability (as a percentage) of completing level i with the fast time.

Output

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
input
1 8
2 8 81
output
3.14
input
2 30
20 30 80
3 9 85
output
31.4
input
4 319
63 79 89
79 97 91
75 87 88
75 90 83
output
314.159265358
Note

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 - 动态规划 - 概率与期望 - 二分答案的主要内容,如果未能解决你的问题,请参考以下文章

Gotta Catch Em' All!

You Gotta Care About the Code

CodeForces - 1520G To Go Or Not To Go?(bfs)

Legacy CodeForces

codeforces #380 div2

Codeforces 1129CMorse Code