Description
Input
Output
Sample Input
2 1 2
1 2 1
0.8 0.2 0.5
1 2 5
1 3 3
2 3 1
Sample Output
/* 这道题搁了很长时间了,现在趁着刚看期望DP,看看这道题目。 f[i][j][0/1]表示前i搁时间段,用了j次换教室的机会,第i次有没有用的最小期望。 然后转移的时候根据上一个时间段有没有换教室来做转移方程就可以了。 */ #include<cstdio> #include<iostream> #include<cstring> #define N 2010 using namespace std; int c[N][2],n,m,v,e,dis[N][N]; double p[N],f[N][N][2]; double fmin(double a,double b){return a<b?a:b;} int main(){ memset(dis,127/3,sizeof(dis)); scanf("%d%d%d%d",&n,&m,&v,&e); for(int i=1;i<=n;i++) scanf("%d",&c[i][0]); for(int i=1;i<=n;i++) scanf("%d",&c[i][1]); for(int i=1;i<=n;i++) scanf("%lf",&p[i]); for(int i=1;i<=e;i++){ int u,v,w;scanf("%d%d%d",&u,&v,&w); dis[u][v]=min(dis[u][v],w); dis[v][u]=min(dis[v][u],w); } for(int i=1;i<=v;i++)dis[i][i]=0; for(int k=1;k<=v;k++) for(int i=1;i<=v;i++) for(int j=1;j<=v;j++) if(i!=j&&i!=k&&k!=j) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) f[i][j][0]=f[i][j][1]=1e60; f[1][0][0]=f[1][1][1]=0; for(int i=2;i<=n;i++){ f[i][0][0]=f[i-1][0][0]+dis[c[i-1][0]][c[i][0]]; f[i][0][1]=1e60; double t1=p[i-1]*dis[c[i-1][1]][c[i][0]]+(1-p[i-1])*dis[c[i-1][0]][c[i][0]]; double t2=p[i]*dis[c[i-1][0]][c[i][1]]+(1-p[i])*dis[c[i-1][0]][c[i][0]]; double t3=p[i-1]*dis[c[i-1][1]][c[i][1]]+(1-p[i-1])*dis[c[i-1][0]][c[i][1]]; for(int j=1;j<=i&&j<=m;j++){ f[i][j][0]=fmin(f[i-1][j][0]+dis[c[i-1][0]][c[i][0]],f[i-1][j][1]+t1); f[i][j][1]=fmin(f[i-1][j-1][0]+t2,f[i-1][j-1][1]+p[i]*t3+(1-p[i])*t1); } } double ans=1e60; for(int i=0;i<=m;i++) ans=fmin(ans,fmin(f[n][i][0],f[n][i][1])); printf("%.2lf",ans); return 0; }