题意:有\(n\)个课程,第\(i\)个课程你原本应在\(c_i\)教室上课,同时又有一堂课在\(d_i\)教室,现在你可以提出m个申请,在第i个课程时到\(d_i\)教室上课,成功概率为\(p_i\),给出总共v个教室构成的图,求最小的路径和的期望,\(1≤n≤2000,0≤m≤2000,1≤v≤300\)
分析:设\(f[i][j][0/1]\)表示前\(i\)节课,申请了\(j\)节课换教室,且第i节课申请(1)或者未申请(0)的最小路径期望.最多只有300个教室,首先可以直接\(floyed\)预处理最短路\(dis[x][y]\).设\(c[i]\)表示第\(i\)节课不换教室所在的教室,\(d[i]\)表示第\(i\)节课换教室之后所在的教室,则有,
\(f[i][j][0]=min(f[i-1][j][0]+dis[c[i-1]][c[i]],f[i-1][j][1]+dis[c[i-1]][c[i]]*(1.0-p[i-1])+dis[d[i-1]][c[i]]*p[i-1]*1.0)\)
\(f[i][j][1]=min(f[i-1][j-1][0]+dis[c[i-1]][c[i]]*(1.0-p[i])+dis[c[i-1]][d[i]]*p[i]*1.0,f[i-1][j-1][1]+dis[d[i-1]][d[i]]*p[i]*p[i-1]*1.0+dis[c[i-1]][d[i]]*p[i]*(1.0-p[i-1])+dis[d[i-1]][c[i]]*(1.0-p[i])*p[i-1]+dis[c[i-1]][c[i]]*(1.0-p[i])*(1.0-p[i-1]))\)
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
inline int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
const int N=2005;
const int M=100005;
int c[N],d[N],dis[305][305];
double p[N],f[N][N][2];
int main(){
int n=read(),m=read(),v=read(),e=read();
for(int i=1;i<=n;i++)c[i]=read();
for(int i=1;i<=n;i++)d[i]=read();
for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
for(int i=1;i<=v;i++)
for(int j=1;j<=v;j++)
dis[i][j]=1e9;
for(int i=1;i<=v;i++)dis[i][i]=0;
for(int i=1;i<=e;i++){
int a=read(),b=read(),c=read();
if(a!=b)dis[b][a]=dis[a][b]=min(dis[a][b],c);
}
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][k]+dis[k][j],dis[i][j]);
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
f[i][j][0]=f[i][j][1]=1e9;
f[1][1][1]=f[1][0][0]=0;
for(int i=2;i<=n;i++){
f[i][0][0]=f[i-1][0][0]+dis[c[i]][c[i-1]];
for(int j=1;j<=i&&j<=m;j++){
f[i][j][0]=min(f[i-1][j][0]+dis[c[i-1]][c[i]],f[i-1][j][1]+dis[c[i-1]][c[i]]*(1.0-p[i-1])+dis[d[i-1]][c[i]]*p[i-1]*1.0);
f[i][j][1]=min(f[i-1][j-1][0]+dis[c[i-1]][c[i]]*(1.0-p[i])+dis[c[i-1]][d[i]]*p[i]*1.0,f[i-1][j-1][1]+dis[d[i-1]][d[i]]*p[i]*p[i-1]*1.0+dis[c[i-1]][d[i]]*p[i]*(1.0-p[i-1])+dis[d[i-1]][c[i]]*(1.0-p[i])*p[i-1]+dis[c[i-1]][c[i]]*(1.0-p[i])*(1.0-p[i-1]));
}
}
double ans=1e9;
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;
}