思路:这道题比较特殊,是一次性提交换不换教室,不能是之前那样实时的考虑,所以考虑的东西比较多,并且不能一下子搞完。详细看代码,一开始入门做还真的是折磨。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,v,e;
int mp[400][400];
int c[3000],d[3000];
double p[3000];
double dp[2200][2200][2];
int main()
{
scanf("%d%d%d%d", &n, &m, &v, &e);
for(int i = 1;i<=n;i++)scanf("%d", &c[i]);
for(int i = 1;i<=n;i++)scanf("%d", &d[i]);
for(int i = 1;i<=n;i++)scanf("%lf", &p[i]);
memset(mp, 0x3f3f3f, sizeof(mp));
for(int i = 1;i<=v;i++)
mp[i][i] = mp[0][i] = 0;
for(int i = 0;i<e;i++)
{
int u,v,w;
scanf("%d%d%d", &u, &v, &w);
mp[u][v] = mp[v][u] = min(w, mp[u][v]);
}
for(int k = 1;k<= v;k++)
{
for(int i = 1;i<=v;i++)
{
for(int j = 1;j<=v;j++)
{
mp[i][j] = min(mp[i][j], mp[i][k]+mp[k][j]);
}
}
}
//初始化
for(int i = 0;i<=n;i++)
{
for(int j = 0;j<=m;j++)
{
for(int k = 0;k<=1;k++)
dp[i][j][k] = 0x3f3f3f;
}
}
dp[1][1][1] = dp[1][0][0] = 0;
for(int i = 2;i<=n;i++)
{
for(int j = 0;j<=m;j++)
{
dp[i][j][0] = min(dp[i-1][j][0] + mp[c[i-1]][c[i]],dp[i-1][j][1]+ mp[c[i-1]][c[i]] *(1-p[i-1]) + mp[d[i-1]][c[i]]*p[i-1]);
if(j)
//前面申请成功和失败的期望
dp[i][j][1] = min(dp[i-1][j-1][0] + mp[c[i-1]][c[i]]*(1-p[i]) + mp[c[i-1]][d[i]] * p[i],
dp[i-1][j-1][1] + mp[c[i-1]][c[i]] *(1-p[i-1] ) *(1-p[i]) //两次申请都失败
+ mp[c[i-1]][d[i]]*(1-p[i-1]) *p[i] //前一次失败后一次成功
+ mp[d[i-1]][c[i]] *p[i-1] *(1-p[i]) //前一次成功后一次失败
+ mp[d[i-1]][d[i]] *p[i-1]*p[i] ); //两次都成功
}
}
double res = 0x3f3f3f;
for(int i = 0;i<=m;i++)
res = min(res, min(dp[n][i][0], dp[n][i][1]));
printf("%.2f\n",res);
return 0;
}