码迷,mamicode.com
首页 > 其他好文 > 详细

NOIP 2016 换教室 | 概率DP

时间:2018-02-27 21:19:35      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:方案   continue   tin   amp   mil   floyd   cst   cstring   ros   

设 dp[i][j][0] 和 dp[i][j][1] 表示在前 i 个里面换了 j 个的最优方案,0 表示当前换,1 表示当前不换。

分为以下几种情况讨论:

当前点不换,上一个不换;

      上一个换(失败 + 成功)。

 

当前点换(失败 + 成功),上一个不换;

             上一个换(失败 + 成功)。

 

得出转移方程如下:

初始条件 dp[1][0][0] = dp[1][1][1] = 0

 dp[i-1][j][0] + floyd[c[i-1]][c[i]]

 dp[i-1][j][1] + floyd[d[i-1]][c[i]] * k[i-1] + floyd[c[i-1]][c[i]] * (1 - k[i-1])

 dp[i-1][j-1][0] + floyd[c[i-1]][d[i]] * k[i] + floyd[c[i-1]][c[i]] * (1 - k[i])

 dp[i-1][j-1][1] + floyd[d[i-1]][d[i]] * k[i-1] * k[i] + floyd[d[i-1]][c[i]] * k[i-1] * (1 - k[i]) + floyd[c[i-1]][d[i]] * (1 - k[i-1]) * k[i] + floyd[c[i-1]][c[i]] * (1 - k[i-1]) * (1 - k[i])

 

最后就是不要忘记 j = 0 的时候是没有 ③ ④ 种情况的,而且 ans 只在 dp[n][ ][ ] 处取,不要把中间状态也打擂了。

 

 1 #include <cstdio>
 2 #include <string>
 3 #include <cstring>
 4 
 5 const int INF = 0x3f3f3f3f;
 6 
 7 int read() {
 8     int x = 0; char c = getchar();
 9     while (!isdigit(c)) c = getchar();
10     while (isdigit(c)) {
11         x = (x << 3) + (x << 1) + (c ^ 48);
12         c = getchar();
13     }
14     return x;
15 }
16 
17 double fmin(double x, double y) {
18     return y > x ? x : y;
19 }
20 
21 int c[2005], d[2005];
22 double k[2005], dp[2005][2005][2], floyd[305][305];
23 
24 int main() {
25     int n = read(), m = read(), v = read(), e = read();
26     for (register int i = 1; i <= n; ++ i) c[i] = read();
27     for (register int i = 1; i <= n; ++ i) d[i] = read();
28     for (register int i = 1; i <= n; ++ i) scanf("%lf", &k[i]);
29     for (register int i = 1; i < v; ++ i)
30         for (register int j = i + 1; j <= v; ++ j)
31             floyd[i][j] = floyd[j][i] = INF;
32     for (register int i = 1; i <= e; ++ i) {
33         int u = read(), v = read(), w  = read();
34         floyd[u][v] = floyd[v][u] = fmin(floyd[u][v], w);
35     }
36     for (register int k = 1; k <= v; ++ k)
37         for (register int i = 1; i < v; ++ i)
38             for (register int j = i + 1; j <= v; ++ j)
39                 if (floyd[i][j] > floyd[i][k] + floyd[k][j])
40                     floyd[i][j] = floyd[j][i] = floyd[i][k] + floyd[k][j];
41     for (register int i = 1; i <= n; ++ i)
42         for (register int j = 0; j <= m; ++ j)
43             dp[i][j][0] = dp[i][j][1] = INF;
44     dp[1][0][0] = dp[1][1][1] = 0;
45     for (register int i = 2; i <= n; ++ i) {
46         for (register int j = 0; j <= m && j <= i; ++ j) {
47             dp[i][j][0] = fmin(dp[i-1][j][0] + floyd[c[i-1]][c[i]],
48                                dp[i-1][j][1] + floyd[d[i-1]][c[i]] * k[i-1] 
49                                              + floyd[c[i-1]][c[i]] * (1 - k[i-1]));
50             if (j == 0) continue;
51             dp[i][j][1] = fmin(dp[i-1][j-1][0] + floyd[c[i-1]][d[i]] * k[i]
52                                                + floyd[c[i-1]][c[i]] * (1 - k[i]), 
53                                dp[i-1][j-1][1] + floyd[d[i-1]][d[i]] * k[i-1] * k[i]
54                                                + floyd[d[i-1]][c[i]] * k[i-1] * (1 - k[i])
55                                                + floyd[c[i-1]][d[i]] * (1 - k[i-1]) * k[i]
56                                                + floyd[c[i-1]][c[i]] * (1 - k[i-1]) * (1 - k[i]));
57         }
58     }
59     double ans = INF;
60     for (register int i = 0; i <= m; ++ i)
61         ans = fmin(ans, fmin(dp[n][i][0], dp[n][i][1]));
62     printf("%.2lf\n", ans);
63     return 0;
64 }

 

NOIP 2016 换教室 | 概率DP

标签:方案   continue   tin   amp   mil   floyd   cst   cstring   ros   

原文地址:https://www.cnblogs.com/milky-w/p/8480497.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!