题意
有个独立的时间段,每个时间段有2节课
对应两个教室,一开始被安排上
的课,但你可以申请换课,换课申请提交后有
概率成功换课.有
个教室,也就是说每节课你需要花时间到指定教室,你想要提交一些申请,使你期望走过的距离和最小.需要注意的是,申请次数有上限
.
数据范围:(
为连接教室的边的数量,为双向边)
题解
首先可以知道,需要处理出两两之间的最短路
然后就是申请的问题
如果没有概率那么就是很明显的一个
状态为,
节课时提交了
个申请且第
节课是否提交申请的最小值
如果加入了概率可以看到其实也是成立的,不过要考虑
时如果申请是否申请成功即可
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 5e6 + 5;
int N, M, V, E;
int c[2005], d[2005];
double p[2005];
int dis[305][305];
double dp[2005][2005][2];
int main(){
int i, j, k;
scanf("%d%d%d%d", &N, &M, &V, &E);
for(i = 1; i <= N; i++) scanf("%d", c + i);
for(i = 1; i <= N; i++) scanf("%d", d + i);
for(i = 1; i <= N; i++) scanf("%lf", p + i);
memset(dis, 60, sizeof(dis));
for(i = 1; i <= E; i++){
int x, y, w;
scanf("%d%d%d", &x, &y, &w);
dis[x][y] = dis[y][x] = min(dis[x][y], w);
}
for(i = 1; i <= V; i++) dis[i][i] = 0;
for(k = 1; k <= V; k++)
for(i = 1; i <= V; i++)
for(j = i + 1; j <= V; j++)
if(dis[i][j] > dis[i][k] + dis[k][j])
dis[i][j] = dis[j][i] = dis[i][k] + dis[k][j];
int top;
for(i = 1; i <= N; i++)
for(j = 0; j <= M; j++) dp[i][j][1] = dp[i][j][0] = 1e9;
dp[1][0][0] = dp[1][1][1] = 0;
for(i = 2; i <= N; i++)
for(j = 0, top = min(i, M); j <= top; j++){
if(j){
dp[i][j][1] = min(dp[i - 1][j - 1][0] +
p[i] * dis[c[i - 1]][d[i]] +
(1 - p[i]) * dis[c[i - 1]][c[i]],
dp[i - 1][j - 1][1] +
p[i - 1] * p[i] * dis[d[i - 1]][d[i]] +
(1 - p[i - 1]) * p[i] * dis[c[i - 1]][d[i]] +
p[i - 1] * (1 - p[i]) * dis[d[i - 1]][c[i]] +
(1 - p[i - 1]) * (1 - p[i]) * dis[c[i - 1]][c[i]]);
dp[i][j][0] = min(dp[i - 1][j][0] +
dis[c[i - 1]][c[i]],
dp[i - 1][j][1] +
p[i - 1] * dis[d[i - 1]][c[i]] +
(1 - p[i - 1]) * dis[c[i - 1]][c[i]] );
}else{
dp[i][j][0] = dp[i - 1][j][0] + dis[c[i - 1]][c[i]];
}
}
double ans = 1e9;
for(i = 0, top = min(N, M); i <= top; i++) ans = min(ans, min(dp[N][i][1], dp[N][i][0]));
printf("%.2lf\n", ans);
return 0;
}

本文探讨了一种在有限申请次数下,通过提交换课申请来最小化学生在多个教室间移动总距离的算法。考虑到每次申请的成功概率,采用动态规划方法求解。文章详细介绍了如何计算两两教室间的最短路径,并在此基础上设计状态转移方程,最终求得期望的最小行走距离。
2448

被折叠的 条评论
为什么被折叠?



