这个问题转化为,在一张无向图上,挑选n个点,使得期望长度最短.
我一开始是把状态设计为F[i, j],表示已经选了i个课程时,申请j次.但是没办法进行状态更新,因为当前路径的长度取决于当前的课程选的教室,也取决于上一个课程选的教室,所以我们将状态设计为F[i, j, 0/1],f[i][j][0]表示前i个时间段中提交了j次申请,最后一次没有提交的最小期望路径长度,f[i][j][1]表示前i个时间段中提交了j次申请,最后一次已经提交的最小期望路径长度.
那么就有状态更新:
代码如下:
#include <bits/stdc++.h>
//#define LOCAL
#define INF 0xf3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false), cin.tie(0)
// #define int long long
#define debug(a) cout << #a << "=" << a << endl;
using namespace std;
const int N = 2010, M = 310;
int n, m, v, e;
int c[N], d[N];
double p[N];
int dis[M][M];
double f[N][N][3];
//f[i][j][0]表示前i个时间段中提交了j次申请,最后一次没有提交的最小期望路径长度
//f[i][j][1]表示前i个时间段中提交了j次申请,最后一次已经提交的最小期望路径长度
signed main(){
#ifdef LOCAL
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
IOS;
cin >> n >> m >> v >> e;
memset(dis, 0x3f, sizeof dis);
for (int i = 1; i <= n; ++i)
dis[i][i] = 0;
for (int i = 1; i <= n; ++i)
cin >> c[i];
for (int i = 1; i <= n; ++i)
cin >> d[i];
for (int i = 1; i <= n; ++i)
cin >> p[i];
for (int i = 1, a, b, w; i <= e; ++i){
cin >> a >> b >> w;
dis[a][b] = dis[b][a] = min(w, dis[a][b]);
}
/* Floyd */
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][j], dis[i][k] + dis[k][j]);
/* Dp */
for (int i = 0; i <= n; ++i)
for (int j = 0; j <= m; ++j)
for (int k = 0; k <= 1; ++k)
f[i][j][k] = 1e9;
f[1][0][0] = f[1][1][1] = 0;
for (int i = 2; i <= n; ++i)
for (int j = 0; j <= min(i, 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 - p[i - 1]) + dis[d[i - 1]][c[i]] * p[i - 1]);
if (!j)
continue;
f[i][j][1] = min(f[i - 1][j - 1][0] + dis[c[i - 1]][d[i]] * p[i] + dis[c[i - 1]][c[i]] * (1 - p[i]),
f[i - 1][j - 1][1] + dis[d[i - 1]][d[i]] * p[i - 1] * p[i] +
dis[c[i - 1]][d[i]] * (1 - p[i - 1]) * p[i] +
dis[d[i - 1]][c[i]] * p[i - 1] * (1 - p[i]) +
dis[c[i - 1]][c[i]] * (1 - p[i - 1]) * (1 - p[i]));
}
double ans = 1e9;
for (int i = 0; i <= m; ++i)
for (int j = 0; j <= 1; ++j)
ans = min(ans, f[n][i][j]);
printf("%.2f\n", ans);
}