problem
数据范围:
1
≤
n
≤
2000
1≤n≤2000
1≤n≤2000,
0
≤
m
≤
2000
0 \leq m \leq 2000
0≤m≤2000,
1
≤
v
≤
300
1 \leq v \leq 300
1≤v≤300,
0
≤
e
≤
90000
0 \leq e \leq 90000
0≤e≤90000。
solution
用 f [ i ] [ j ] [ 0 / 1 ] f[i][j][0/1] f[i][j][0/1] 表示在前 i i i 个时间段申请换了 j j j 次课,且第 i i i 个时间段不换课 / / /换课的最小期望值。
下面的 d i s [ i ] [ j ] dis[i][j] dis[i][j] 表示 i i i 到 j j j 的最短路,由于点比较少,可以直接 floyd 求。
当第 i i i 节课不申请换的时候(即 f ( i , j , 0 ) f(i,j,0) f(i,j,0))
如果第 i − 1 i-1 i−1 节课不申请换,贡献 d i s [ c i − 1 ] [ c i ] + f [ i − 1 ] [ j ] [ 0 ] dis[c_{i-1}][c_i]+f[i-1][j][0] dis[ci−1][ci]+f[i−1][j][0]。
如果第 i − 1 i-1 i−1 节课申请换,那有两种情况:
- 换课成功,贡献 k i − 1 × ( d i s [ d i − 1 ] [ c i ] + f [ i − 1 ] [ j ] [ 1 ] ) k_{i-1}\times(dis[d_{i-1}][c_i]+f[i-1][j][1]) ki−1×(dis[di−1][ci]+f[i−1][j][1])。
- 换课失败,贡献 ( 1 − k i − 1 ) × ( d i s [ c i − 1 ] [ c i ] + f [ i − 1 ] [ j ] [ 1 ] ) (1-k_{i-1})\times(dis[c_{i-1}][c_i]+f[i-1][j][1]) (1−ki−1)×(dis[ci−1][ci]+f[i−1][j][1])。
取个 min \min min 即可。
当第 i i i 节课申请换的时候(即 f ( i , j , 1 ) f(i,j,1) f(i,j,1))
如果第 i − 1 i-1 i−1 节课不申请换:
- 第 i i i 节换课成功,贡献 k i × ( d i s [ c i − 1 ] [ d i ] + f [ i − 1 ] [ j − 1 ] [ 0 ] ) k_i\times (dis[c_{i-1}][d_i]+f[i-1][j-1][0]) ki×(dis[ci−1][di]+f[i−1][j−1][0])。
- 第 i i i 节换课失败,贡献 ( 1 − k i ) × ( d i s [ c i − 1 ] [ c i ] + f [ i − 1 ] [ j − 1 ] [ 0 ] ) (1-k_i)\times (dis[c_{i-1}][c_i]+f[i-1][j-1][0]) (1−ki)×(dis[ci−1][ci]+f[i−1][j−1][0])。
如果第 i − 1 i-1 i−1 节课申请换:
- 第 i i i 节换课成功,第 i − 1 i-1 i−1 节换课成功,贡献 k i × k i − 1 × ( d i s [ d i − 1 ] [ d i ] + f [ i − 1 ] [ j − 1 ] [ 1 ] ) k_i\times k_{i-1}\times (dis[d_{i-1}][d_i]+f[i-1][j-1][1]) ki×ki−1×(dis[di−1][di]+f[i−1][j−1][1])。
- 第 i i i 节换课成功,第 i − 1 i-1 i−1 节换课失败,贡献 k i × ( 1 − k i − 1 ) × ( d i s [ c i − 1 ] [ d i ] + f [ i − 1 ] [ j − 1 ] [ 1 ] ) k_i\times (1-k_{i-1})\times (dis[c_{i-1}][d_i]+f[i-1][j-1][1]) ki×(1−ki−1)×(dis[ci−1][di]+f[i−1][j−1][1])。
- 第 i i i 节换课失败,第 i − 1 i-1 i−1 节换课成功,贡献 ( 1 − k i ) × k i − 1 × ( d i s [ d i − 1 ] [ c i ] + f [ i − 1 ] [ j − 1 ] [ 1 ] ) (1-k_i)\times k_{i-1}\times (dis[d_{i-1}][c_i]+f[i-1][j-1][1]) (1−ki)×ki−1×(dis[di−1][ci]+f[i−1][j−1][1])。
- 第 i i i 节换课失败,第 i − 1 i-1 i−1 节换课失败,贡献 ( 1 − k i ) × ( 1 − k i − 1 ) × ( d i s [ c i − 1 ] [ c i ] + f [ i − 1 ] [ j − 1 ] [ 1 ] ) (1-k_i)\times (1-k_{i-1})\times (dis[c_{i-1}][c_i]+f[i-1][j-1][1]) (1−ki)×(1−ki−1)×(dis[ci−1][ci]+f[i−1][j−1][1])。
看起来比较麻烦,但是思维很简单。
时间复杂度 O ( v 3 + n m ) O(v^3+nm) O(v3+nm)。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 2005
using namespace std;
int n,m,v,e;
int c[N],d[N],dis[N][N];
double K[N],f[N][N][2];
int main(){
int x,y,z;
scanf("%d%d%d%d",&n,&m,&v,&e);
for(int i=1;i<=n;++i) scanf("%d",&c[i]);
for(int i=1;i<=n;++i) scanf("%d",&d[i]);
for(int i=1;i<=n;++i) scanf("%lf",&K[i]);
memset(dis,127/3,sizeof(dis));
for(int i=1;i<=e;++i){
scanf("%d%d%d",&x,&y,&z);
dis[x][y]=dis[y][x]=min(dis[x][y],z);
}
for(int k=1;k<=v;++k)
for(int i=1;i<=v;++i)
for(int j=1;j<=v;++j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for(int i=1;i<=v;++i) dis[i][i]=0;
for(int i=1;i<=n;++i)
for(int j=0;j<=m;++j)
f[i][j][0]=f[i][j][1]=1e18;
f[1][0][0]=f[1][1][1]=0;
for(int i=2;i<=n;++i){
for(int j=0;j<=m;++j){
f[i][j][0]=min(f[i-1][j][0]+dis[c[i-1]][c[i]],f[i-1][j][1]+K[i-1]*dis[d[i-1]][c[i]]+(1-K[i-1])*dis[c[i-1]][c[i]]);
if(j>0) f[i][j][1]=min(f[i-1][j-1][0]+dis[c[i-1]][d[i]]*K[i]+dis[c[i-1]][c[i]]*(1-K[i]),f[i-1][j-1][1]+dis[d[i-1]][d[i]]*K[i-1]*K[i]+dis[c[i-1]][d[i]]*(1-K[i-1])*K[i]+dis[d[i-1]][c[i]]*K[i-1]*(1-K[i])+dis[c[i-1]][c[i]]*(1-K[i-1])*(1-K[i]));
}
}
double ans=1<<30;
for(int i=0;i<=m;++i) ans=min(ans,min(f[n][i][0],f[n][i][1]));
printf("%.2lf\n",ans);
return 0;
}