f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k] : i i i表示走完前 i i i个教室, j j j表示换了 j j j次, k k k表示当前教室有没有换。
d [ i ] d[i] d[i]为两个教室之间的最短距离。
转移中的几种情况应该都比较好理解…(懒…)
#include<bits/stdc++.h>
#define min(a,b) ((a)<(b))?(a):(b)
using namespace std;
const double inf=1e17+5;
int n,m,v,e,c[2005][2],d[305][305];
double k[2005],f[2005][2005][2],ans=inf;
int main(){
memset(d,63,sizeof(d));
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",&k[i]);
for(int i=1,x,y,z;i<=e;++i){
scanf("%d%d%d",&x,&y,&z);
d[x][y]=d[y][x]=min(d[x][y],z);
}
for(int i=1;i<=v;++i) d[i][i]=d[i][0]=d[0][i]=0;
for(int l=1;l<=v;++l)
for(int i=1;i<=v;++i)
for(int j=1;j<=v;++j)
d[i][j]=min(d[i][j],d[i][l]+d[l][j]);
for(int i=0;i<=n;++i)
for(int j=0;j<=m;++j)
f[i][j][0]=f[i][j][1]=inf;
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]+d[c[i-1][0]][c[i][0]];
for(int j=1,mm=min(i,m);j<=mm;++j){
int x=c[i-1][0],y=c[i-1][1],z=c[i][0],w=c[i][1];
f[i][j][0]=min(f[i][j][0],min(f[i-1][j][0]+d[x][z],f[i-1][j][1]+d[x][z]*(1-k[i-1])+d[y][z]*k[i-1]));
f[i][j][1]=min(f[i][j][1],min(f[i-1][j-1][0]+d[x][z]*(1-k[i])+d[x][w]*k[i],f[i-1][j-1][1]+d[y][w]*k[i]*k[i-1]+d[y][z]*k[i-1]*(1-k[i])+d[x][w]*(1-k[i-1])*k[i]+d[x][z]*(1-k[i-1])*(1-k[i])));
}
}for(int i=0;i<=m;++i) ans=min(ans,min(f[n][i][0],f[n][i][1]));
return !printf("%.2lf",ans);
}