版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82083960
题解:
本蒟蒻第一次知道期望是啥意思。。很简单,就是全部概率*价值求和
感觉期望差不多都和DP有关吧
设
表示选到第i节课,已经申请了换j节课,其中第i节选/不选的期望。
dis用floyd处理一下即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 2001;
int c[MAXN], d[MAXN];
double k[MAXN];
int dis[301][301];
double dp[MAXN][MAXN][2];
inline int read(){
int k = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
return k * f;
}
int main(){
memset(dp, 0x43, sizeof(dp));
memset(dis, 0x3f, sizeof(dis));
int n = read(), m = read(), N = read(), M = read();
for(int i = 1; i <= n; i++){
c[i] = read();
}
for(int i = 1; i <= n; i++){
d[i] = read();
}
for(int i = 1; i <= n; i++){
scanf("%lf", &k[i]);
}
for(int i = 1; i <= N; i++){
dis[i][i] = 0;
}
for(int i = 1; i <= M; i++){
int a = read(), b = read(), l = read();
dis[a][b] = dis[b][a] = min(dis[a][b], l);
}
for(int K = 1; K <= N; K++){
for(int i = 1; i <= N; i++){
for(int j = 1; j < i; j++){
if(dis[i][j] > dis[i][K] + dis[K][j]){
dis[i][j] = dis[j][i] = dis[i][K] + dis[K][j];
}
}
}
}
dp[1][0][0] = dp[1][1][1] = 0;
for(int i = 2; i <= n; i++){
for(int j = 0; j <= min(i, m); j++){
dp[i][j][0] = min(
dp[i - 1][j][1] + (double)dis[c[i - 1]][c[i]] * (1.0 - k[i - 1])
+ (double)dis[d[i - 1]][c[i]] * k[i - 1],
dp[i - 1][j][0] + (double)dis[c[i - 1]][c[i]]
);
if(j){
dp[i][j][1] = min(
dp[i - 1][j - 1][0] + (double)dis[c[i - 1]][d[i]] * k[i]
+ (double)dis[c[i - 1]][c[i]] * (1.0 - k[i]),
dp[i - 1][j - 1][1] + (double)dis[d[i - 1]][d[i]] * k[i - 1] * k[i]
+ (double)dis[d[i - 1]][c[i]] * k[i - 1] * (1.0 - k[i])
+ (double)dis[c[i - 1]][d[i]] * (1.0 - k[i - 1]) * k[i]
+ (double)dis[c[i - 1]][c[i]] * (1.0 - k[i - 1]) * (1.0 - k[i])
);
}
}
}
double Ans = 2147483647;
for(int i = 0; i <= m; i++){
Ans = min(Ans, min(dp[n][i][0], dp[n][i][1]));
}
printf("%.2lf", Ans);
return 0;
}
//dp[i][j][0/1] 第i节课,第j次机会换/不换