这道题很显然是dp,刚开始我是设dp[i][j]表示到第 i 个时间段,申请了 j 个课程耗费的体力值的总和的最小期望值,但是想了半天也没有推出转移方程,现在想想觉得应该是无法表示他第 i 时刻在哪一个教室。
于是我们加一维dp[i][j][0/1]表示第 i 时刻我们是否申请了换教室。那么dp方程就很好推出来了:
先令u1 = c[i - 1], v1 = c[i], u2 = d[i - 1], v2 = d[i]
dp[i][j][0] = min(dp[i - 1][j][0] + v[u1][v1], dp[i - 1][j][1] + v[u2][v1] * k[i - 1] + v[u1][v1] * (1 - k[i - 1]))
dp[i][j][1] = min(dp[i - 1][j - 1][0] + v[u1][v2] * k[i] + v[u1][v1] * (1 - k[i]),
dp[i - 1][j - 1][1] + v[u2][v2] * k[i - 1] * k[i] + v[u1][v2] * (1 - k[i - 1]) * k[i] + v[u2][v1] * k[i - 1] * (1 - k[i]) + v[u1][v1] * (1 - k[i - 1]) * (1 - k[i]))
总的来说,就是如果这一次申请换教室的话,要同时考虑换教室成功和不成功的两种情况。
然后ans = min(dp[n][i][0], dp[n][i][1]) (0 <= i <= m,因为可以不申请换任何一个教室)
然后求多源最短路,又因为V <= 300,直接floyd预处理就行。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a) memset(a, 0, sizeof(a)) 15 typedef long long ll; 16 typedef double db; 17 const int INF = 0x3f3f3f3f; 18 const db eps = 1e-8; 19 const int max_nod = 305; 20 const int maxn = 2e3 + 5; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) x = -x, putchar('-'); 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n, m, V, E; 38 ll v[max_nod][max_nod]; 39 int a[maxn], b[maxn]; 40 db p[maxn]; 41 db dp[maxn][maxn][2]; 42 43 void init() 44 { 45 for(int i = 1; i <= V; ++i) 46 for(int j = 1; j <= V; ++j) v[i][j] = INF; 47 for(int i = 1; i <= n; ++i) 48 for(int j = 0; j <= m; ++j) dp[i][j][0] = dp[i][j][1] = INF; //j:0开始 49 } 50 51 int main() 52 { 53 n = read(); m = read(); V = read(); E = read(); 54 for(int i = 1; i <= n; ++i) a[i] = read(); 55 for(int i = 1; i <= n; ++i) b[i] = read(); 56 for(int i = 1; i <= n; ++i) scanf("%lf", &p[i]); 57 init(); 58 for(int i = 1; i <= E; ++i) 59 { 60 int x = read(), y = read(); ll co = read(); 61 v[x][y] = v[y][x] = min(v[x][y], co); 62 } 63 for(int k = 1; k <= V; ++k) 64 for(int i = 1; i <= V; ++i) 65 for(int j = 1; j <= V; ++j) 66 v[i][j] = min(v[i][j], v[i][k] + v[k][j]); 67 for(int i = 1; i <= V; ++i) v[i][i] = v[i][0] = v[0][i] = 0; 68 dp[1][0][0] = dp[1][1][1] = 0; 69 for(int i = 2; i <= n; ++i) 70 { 71 dp[i][0][0] = dp[i - 1][0][0] + v[a[i - 1]][a[i]]; 72 for(int j = 1; j <= min(i, m); ++j) 73 { 74 db tp_0 = dp[i - 1][j][0] + v[a[i - 1]][a[i]]; 75 db tp_1 = dp[i - 1][j][1] + (db)v[b[i - 1]][a[i]] * p[i - 1] + (db)v[a[i - 1]][a[i]] * (1 - p[i - 1]); 76 dp[i][j][0] = min(dp[i][j][0], min(tp_0, tp_1)); 77 tp_0 = dp[i - 1][j - 1][0] + (db)v[a[i - 1]][b[i]] * p[i] + (db)v[a[i - 1]][a[i]] * (1 - p[i]); 78 tp_1 = dp[i - 1][j - 1][1] + (db)v[b[i - 1]][b[i]] * p[i - 1] * p[i] + (db)v[a[i - 1]][b[i]] * (1 - p[i - 1]) * p[i]; 79 tp_1 += (db)v[b[i - 1]][a[i]] * p[i - 1] * (1 - p[i]) + (db)v[a[i - 1]][a[i]] * (1 - p[i - 1]) * (1 - p[i]); 80 dp[i][j][1] = min(dp[i][j][1], min(tp_0, tp_1)); 81 } 82 } 83 db ans = INF; 84 for(int i = 0; i <= m; ++i) ans = min(ans, min(dp[n][i][0], dp[n][i][1])); 85 printf("%.2lf ", ans); 86 return 0; 87 }