题目大意:学校有v个教室,要上n节课,学校里有e条道路连接教室,每节课还有一个可以替换的教室,并且有ki的概率替换原有教室,现有m次申请替换教室的机会,问经过的路径的期望的最小值
思路:期望dp,首先用floyd算法枚举每个点作为拐点,求出每两间教室之间的最短距离,然后设置状态dp[i][j][k]表示上了i节课换了j次教室,k表示当前课换没换教室,在转移时,如果当前课没换,只要考虑前一节课有没有换,换了有没有成功,如果当前课换了教室,要考虑上一节课换没换,换了成没成功和当前课成没成功
#include<bits/stdc++.h>
using namespace std;
int n, m, v, e;
const int N = 2005;
int ma[305][505];
int c[N][N];
double k[N];
double dp[N][N][2];
const double INF = 1e9;
int main()
{
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]);//更换教室的成功率
}
memset(ma, 63, sizeof ma);
for (int i = 1; i <= e; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);//从u到v有一条长为w的路
ma[u][v] = ma[v][u] = min(ma[u][v], w);//同样两个点可能有多条路
}
for (int k = 1; k <= v; k++)
{
for (int i = 1; i <= v; i++)
{
for (int j = 1; j <= v; j++)
{
ma[i][j] = min(ma[i][j], ma[i][k] + ma[k][j]);
//floyd算法,枚举每个点作为拐点,求出每两个点之间的最短路
}
}
}
for (int i = 1; i <= v; i++)
{
ma[i][i] = 0;//同教室间路线长度为0
}
for (int i = 0; i <= n; i++)
{
for (int j = 0; j <= m; j++)
{
dp[i][j][0] = dp[i][j][1] = INF;
}//求最小值,先把所有值初始化成最大
}
dp[1][0][0] = dp[1][1][1] = 0;
for (int i = 2; i <= n; i++)
{
dp[i][0][0] = dp[i - 1][0][0] + ma[c[i - 1][0]][c[i][0]];
//不换教室的话,期望就是上一时间段没换教室加上个教室到这个教室的距离
for (int j = 1; j <= min(i, m); j++)
{
int o1 = c[i - 1][0], o2 = c[i - 1][1], o3 = c[i][0], o4 = c[i][1];
dp[i][j][0] = min(dp[i - 1][j][0] + ma[o1][o3], dp[i - 1][j][1] + ma[o2][o3] * k[i - 1] + ma[o1][o3] * (1 - k[i - 1]));
//这次没换的期望就是上一次没换,或者上一次换了且成功,或者上一次换了但没成功
dp[i][j][1] = min(dp[i - 1][j - 1][0] + ma[o1][o4] * k[i] + ma[o1][o3] * (1 - k[i]), dp[i - 1][j - 1][1] + ma[o2][o3] * k[i - 1] * (1 - k[i]) + ma[o1][o3] * (1 - k[i - 1]) * (1 - k[i]) + ma[o1][o4] * (1 - k[i - 1]) * k[i] + ma[o2][o4] * k[i - 1] * k[i]);
//这次换了的期望就是上一次没换且这次换失败了,或者上一次没换但这次换成功了
//或者上一次换了没成功但这次成功了,或者上一次换了没成功这次也成功
//或者上一次换了成功了但这次没成功,或者上一次换了没成功但这次成功了
}
}
double ans = INF;
for (int i = 0; i <= m; i++)
{
ans = min(ans, min(dp[n][i][0], dp[n][i][1]));
}
printf("%.2lf", ans);
return 0;
}