洛谷P1850 换教室
最短路 + 动态规划
题解 首先预处理出任意两点的最短路
然后 dp
f[ i ][ j ][ 0/1 ] 现在是 第 i 个时间段,已经申请 过 j次了,该次是否成功 0 否 1 成功 的最小的期望
主要是四个方面的转移 前一个是否申请 成功 or失败 当前是否申请 成功or失败
1 #include <bits/stdc++.h> 2 #define For(i,j,k) for(int i=j;i<=k;i++) 3 using namespace std ; 4 5 const int N = 2011,V = 311,inf = 1e9 ; 6 int a[N],b[N] ; 7 double d[V][V],c[N] ; 8 double f[N][N][2] ; 9 int n,m,v,e ; 10 11 inline void init() // 初始化 12 { 13 For(i,0,V-1) 14 For(j,0,V-1) 15 if(i==j) 16 d[ i ][ j ] = 0 ; 17 else 18 d[ i ][ j ] = inf ; 19 20 For(i,0,N-1) 21 For(j,0,N-1) 22 f[ i ][ j ][ 0 ] = f[ i ][ j ][ 1 ] = inf ; 23 f[ 1 ][ 0 ][ 0 ] = 0 ; //第一个点要么从 a 出发 要么从 b出发 24 f[ 1 ][ 1 ][ 1 ] = 0 ; 25 } 26 27 inline void floyd() 28 { 29 For(k,1,v) 30 For(i,1,v) 31 For(j,1,v) 32 d[ i ][ j ] = min(d[ i ][ j ],d[ i ][ k ]+d[ k ][ j ]) ; // 33 } 34 35 int main() 36 { 37 scanf("%d%d%d%d",&n,&m,&v,&e) ; 38 For(i,1,n) scanf("%d",&a[ i ]) ; 39 For(i,1,n) scanf("%d",&b[ i ]) ; 40 For(i,1,n) scanf("%lf",&c[ i ]) ; 41 init() ; 42 43 For(i,1,e) 44 { 45 int x,y,z ; 46 scanf("%d%d%d",&x,&y,&z) ; 47 if(x==y) continue ; 48 if(z < d[x][y]) d[x][y] = z ; 49 d[y][x] = d[x][y] ; 50 } 51 floyd() ; 52 For(i,2,n) 53 { 54 f[ i ][ 0 ][ 0 ] = f[ i-1 ][ 0 ][ 0 ] + d[a[ i-1 ]][a[ i ]] ; 55 For(j,1,min(m,i)) 56 { 57 f[i][j][0] = min(f[i-1][j][0] + d[a[i-1]][a[i]],f[i-1][j][1] + d[a[i-1]][a[i]] * (1.0-c[ i-1 ]) + d[b[i-1]][a[i]] * c[ i-1 ]) ; 58 f[i][j][1] = f[i-1][j-1][0] + d[a[i-1]][a[i]] * (1.0-c[i]) + d[a[i-1]][b[ i ]] * c[ i ] ; 59 double t = f[i-1][j-1][1] +d[a[i-1]][a[i]] * (1.0-c[i-1]) * (1.0-c[i]) ; 60 t += d[b[i-1]][a[i]] * c[ i-1 ] * (1.0-c[ i ]) ; 61 t += d[a[i-1]][b[i]] * (1.0-c[i-1]) * c[ i ] ; 62 t += d[b[i-1]][b[i]] * c[i-1] * c[i] ; 63 f[i][j][1] = min(f[i][j][1],t) ; 64 } 65 } 66 double ans = f[n][0][0] ; 67 For(i,1,m) 68 ans = min( ans,min( f[n][i][0],f[n][i][1] ) ) ; 69 printf("%.2lf ",ans) ; 70 return 0 ; 71 }