令人印象深刻的状态转移方程...
f[i][j][0/1]表示前i个换j次,第i次是否申请时的期望。
注意可能有重边,自环。
转移要分类讨论,距离是上/这次成功/失败的概率乘相应的路程。
从上次的0/1中取min
1 #include2 #include 3 #include 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 /// floyd53 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...