网上题解大致都有
我只是贴上来标记一下而已
总的来说测试时没有去考虑这一题是比较可惜的,因为没有看过太多关于期望的题就直接放弃了
只能说细节比较多,推方程什么的中规中矩不算难吧
只是还是参考了一下别人的罢了
#include<cstdio>
#include<algorithm>
#define RG register
#define INF 2e8
using namespace std;
inline int read()
{
int a=0,f=1;static char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){a=a*10+c-'0';c=getchar();}
return a*f;
}
int n,m,v,e;
int c[2001],d[2001],dis[301][301];
double p[2001],f[2001][2001][2]; //f[i][j][1/0]表示在第i个时间段,第j次申请,1/0表示是否申请成功
void floyd()
{
RG int i,j,k;
for(k=1;k<=v;++k)
for(i=1;i<=v;++i)
for(j=1;j<=v;++j)
if(i!=j&&j!=k)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int main()
{
n=read(),m=read(),v=read(),e=read();
RG int i,j;
for(i=1;i<=n;++i) c[i]=read();
for(i=1;i<=n;++i) d[i]=read();
for(i=1;i<=n;++i) scanf("%lf",&p[i]);
for(i=1;i<=v;++i)
{
for(j=1;j<=v;++j) dis[i][j]=INF;
dis[i][i]=0;
}
for(i=1;i<=e;++i)
{
int x=read(),y=read(),z=read();
dis[x][y]=min(dis[x][y],z);
dis[y][x]=dis[x][y];
}
floyd();
for(i=1;i<=n;++i)
for(j=0;j<=m;++j)
f[i][j][0]=f[i][j][1]=INF;
f[1][0][0]=f[1][1][1]=0;
for(i=2;i<=n;++i)
for(j=0;j<=min(i,m);++j)
{
int cc=dis[c[i-1]][c[i]],cd=dis[c[i-1]][d[i]],dc=dis[d[i-1]][c[i]],dd=dis[d[i-1]][d[i]];
double p1=p[i-1],p2=p[i];
if(j<=i-1) f[i][j][0]=min(p1*dc+(1-p1)*cc+f[i-1][j][1],cc+f[i-1][j][0]);
if(j>0) f[i][j][1]=min(f[i-1][j-1][0]+p2*cd+(1-p2)*cc,f[i-1][j-1][1]+p1*p2*dd+p1*(1-p2)*dc+(1-p1)*p2*cd+(1-p1)*(1-p2)*cc);//总之不是很难就对了
}
double ans=INF;
for(i=0;i<=min(n,m);++i)
ans=min(ans,min(f[n][i][0],f[n][i][1]));
printf("%.2lf\n",ans);
return 0;
}