[NOIP2016]換教室
阿新 • • 發佈:2018-12-11
:表示走完前個教室,表示換了次,表示當前教室有沒有換。
為兩個教室之間的最短距離。
轉移中的幾種情況應該都比較好理解…(懶…)
#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); }