洛谷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 }
我一开始把ans初值设的是0...