NOIP 2016 换教室 | 概率DP

Posted milky-w

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP 2016 换教室 | 概率DP相关的知识,希望对你有一定的参考价值。

设 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的主要内容,如果未能解决你的问题,请参考以下文章

NOIp2016Day1T3--换教室--概率dp+floyd

[NOIP2016]换教室

bzoj 4720: [Noip2016]换教室期望dp

uoj262 NOIP2016—换教室

NOIP2016换教室(DP,期望)

[NOIP2016]换教室 D1 T3 Floyed+期望DP