题目
注:以上图片截图自洛谷
分析
这道题概率DP,前置知识:数学期望
part 1 状态
dp [ 第 i 个时间段 ] [ 换了 j 次 ] [ 当前是否换了 ] = 最优方案的期望值
part 2 转移
我们把期望下放到每条路;
你可以选择申请或不申请;
如果选择申请:期望的路径长 = (申请成功的路径长) * 申请成功概率 + (申请不成功的路径长) * 申请不成功概率
这里注意不要被样例解释误导了,推导一下他们其实是一样的,因为我们的状态是:dp [ 第 i 个时间段 ] [ 换了 j 次 ] [ 当前是否换了 ] = 最优方案的期望值
代码
1 /************************* 2 User:Mandy.H.Y 3 Language:c++ 4 Problem:luogu1850 5 Algorithm: 6 *************************/ 7 8 #include<bits/stdc++.h> 9 10 using namespace std; 11 12 const int maxn = 2005; 13 const int maxv = 305; 14 const int maxe = 90005; 15 16 int n,m,v,e,size; 17 int c[maxn],d[maxn]; 18 double k[maxn],dp[maxn][maxn][3]; 19 int g[maxv][maxv]; 20 21 struct Edge{ 22 int v,nt,w; 23 }edge[maxe << 1]; 24 25 template<class T>inline void read(T &x){ 26 x = 0;bool flag = 0;char ch = getchar(); 27 while(!isdigit(ch)) flag |= ch == '-',ch = getchar(); 28 while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar(); 29 if(flag) x = -x; 30 } 31 32 template<class T>void putch(const T x){ 33 if(x > 9) putch(x / 10); 34 putchar(x % 10 | 48); 35 } 36 37 template<class T>void put(const T x){ 38 if(x < 0) putchar('-'),putch(-x); 39 else putch(x); 40 } 41 42 void file(){ 43 freopen("1850.in","r",stdin); 44 freopen("1850.out","w",stdout); 45 } 46 47 void readdata(){ 48 memset(g,0x3f3f3f3f,sizeof(g)); 49 read(n);read(m);read(v);read(e); 50 for(int i = 1;i <= v; ++ i) g[i][i] = 0; 51 for(int i = 1;i <= n; ++ i) read(c[i]); 52 for(int i = 1;i <= n; ++ i) read(d[i]); 53 for(int i = 1;i <= n; ++ i) scanf("%lf",&k[i]); 54 for(int i = 1;i <= e; ++ i) { 55 int u,v,w; 56 read(u);read(v);read(w); 57 g[u][v] = min(g[u][v],w); 58 g[v][u] = g[u][v]; 59 } 60 } 61 62 void Floyd(){ 63 for(int l = 1;l <= v; ++ l) 64 for(int i = 1;i <= v; ++ i) 65 for(int j = 1;j <= v; ++ j){ 66 if(g[i][l] != 0x3f3f3f3f && g[l][j] != 0x3f3f3f3f) 67 if(g[i][l] + g[l][j] < g[i][j]) g[i][j] = g[i][l] + g[l][j]; 68 } 69 } 70 71 void work(){ 72 73 Floyd(); 74 75 for(int i = 2;i <= n; ++ i){ 76 77 int u1 = c[i - 1],u2 = d[i - 1]; 78 int v1 = c[i],v2 = d[i]; 79 80 dp[i][0][0] = dp[i - 1][0][0] + g[u1][v1]; 81 82 for(int j = 1;j <= m; ++ j){ 83 84 dp[i][j][0] = min(dp[i - 1][j][0] + g[u1][v1], 85 dp[i - 1][j][1] + 86 k[i - 1] * g[u2][v1] + 87 (1 - k[i - 1]) * g[u1][v1]); 88 89 dp[i][j][1] = dp[i - 1][j - 1][0] + 90 k[i] * g[u1][v2] + 91 (1 - k[i]) * g[u1][v1]; 92 if(j > 1) dp[i][j][1] = min(dp[i][j][1],dp[i - 1][j - 1][1] + 93 k[i - 1] * k[i] * g[u2][v2] + 94 k[i - 1] * (1 - k[i]) * g[u2][v1] + 95 (1 - k[i - 1]) * k[i] * g[u1][v2] + 96 (1 - k[i - 1]) * (1 - k[i]) * g[u1][v1]); 97 98 } 99 } 100 double ans = 2000000000.0; 101 for(int i = 0;i <= m; ++ i) { 102 ans = min(ans,dp[n][i][0]); 103 if(i > 0) ans = min(ans,dp[n][i][1]); 104 } 105 106 printf("%.2lf",ans); 107 } 108 109 int main(){ 110 // file(); 111 readdata(); 112 work(); 113 return 0; 114 }