洛谷P1850 换教室

令人印象深刻的状态转移方程...

f[i][j][0/1]表示前i个换j次,第i次是否申请时的期望。

注意可能有重边,自环。

转移要分类讨论,距离是上/这次成功/失败的概率乘相应的路程。

从上次的0/1中取min

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 const int N = 310, M = 2010;
 5 const double INF = 1.0 * 0x3f3f3f3f;
 6 
 7 inline void read(int &x) {
 8     x = 0;
 9     char c = getchar();
10     while(c > '9' || c < '0') {
11         c = getchar();
12     }
13     while(c >= '0' && c <= '9') {
14         x = (x << 1) + (x << 3) + c - 48;
15         c = getchar();
16     }
17     return;
18 }
19 
20 int G[N][N], a[M], b[M];
21 double k[M], f[M][M][2];
22 
23 int main() {
24     int n, m, v, e;
25     read(n);
26     read(m);
27     read(v);
28     read(e);
29     for(int i = 1; i <= n; i++) {
30         read(a[i]);
31     }
32     for(int i = 1; i <= n; i++) {
33         read(b[i]);
34     }
35     for(int i = 1; i <= n; i++) {
36         scanf("%lf", &k[i]);
37     }
38     int x, y, z;
39     memset(G, 0x3f, sizeof(G));
40     for(int i = 1; i <= e; i++) {
41         read(x);
42         read(y);
43         read(z);
44         if(G[x][y]) {
45             G[y][x] = G[x][y] = std::min(G[x][y], z);
46         }
47         else {
48             G[x][y] = G[y][x] = z;
49         }
50     }
51 
52     /// floyd
53     for(int i = 1; i <= v; i++) {
54         G[i][i] = 0;
55     }
56     for(int p = 1; p <= v; p++) {
57         for(int i = 1; i <= v; i++) {
58             for(int j = 1; j <= v; j++) {
59                 G[i][j] = std::min(G[i][j], G[i][p] + G[p][j]);
60             }
61         }
62     }
63 
64     for(int i = 1; i <= n; i++) {
65         for(int j = 0; j <= m; j++) {
66             f[i][j][0] = f[i][j][1] = INF;
67         }
68     }
69     f[1][0][0] = f[1][1][1] = 0;
70     for(int i = 2; i <= n; i++) {
71         for(int j = 0; j <= m; j++) {
72             f[i][j][0] = std::min(f[i - 1][j][0] + G[a[i - 1]][a[i]],
73                                   f[i - 1][j][1]
74                                   + G[b[i - 1]][a[i]] * k[i - 1]
75                                   + G[a[i - 1]][a[i]] * (1 - k[i - 1]));
76             if(j) {
77                 f[i][j][1] = std::min(f[i - 1][j - 1][0]
78                                       + G[a[i - 1]][b[i]] * k[i]
79                                       + G[a[i - 1]][a[i]] * (1 - k[i]),
80                                       f[i - 1][j - 1][1]
81                                       + G[b[i - 1]][b[i]] * k[i - 1] * k[i]
82                                       + G[b[i - 1]][a[i]] * k[i - 1] * (1 - k[i])
83                                       + G[a[i - 1]][b[i]] * (1 - k[i - 1]) * k[i]
84                                       + G[a[i - 1]][a[i]] * (1 - k[i - 1]) * (1 - k[i]));
85             }
86         }
87     }
88 
89     double ans = INF;
90 
91     for(int i = 0; i <= m; i++) {
92         ans = std::min(ans, f[n][i][0]);
93         ans = std::min(ans, f[n][i][1]);
94     }
95     printf("%.2lf", ans);
96 
97     return 0;
98 }
AC代码

我一开始把ans初值设的是0...

原文地址:https://www.cnblogs.com/huyufeifei/p/9665136.html