# noip2016 换教室

## 输入输出样例

3 2 3 3
2 1 2
1 2 1
0.8 0.2 0.5
1 2 5
1 3 3
2 3 1


2.80

## 说明

【样例1说明】

【提示】

1. 道路中可能会有多条双向道路连接相同的两间教室。 也有可能有道路两端连接

2.请注意区分n,m,v,e的意义, n不是教室的数量, m不是道路的数量。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <string>

using namespace std;

int n, m, v, e, c[2010], d[2010], map[310][310];
double dp[2010][2010][2];
double k[2010],ans;

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", &k[i]);
for (int i = 1; i <= v; i++)
for (int j = 1; j <= v; j++)
if (i != j)
map[i][j] = 1000000000;
for (int i = 1; i <= e; i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
map[a][b] = min(map[a][b], w);
map[b][a] = map[a][b];
}
//floyd
for (int k = 1; k <= v; k++)
for (int i = 1; i <= v; i++)
for (int j = 1; j <= v; j++)
if (map[i][k] + map[k][j] < map[i][j])
map[i][j] = map[i][k] + map[k][j];

for (int i = 1; i <= n; i++)
for (int j = 0; j <= m; j++)
dp[i][j][0] = dp[i][j][1] = 1e30;
dp[1][0][0] = dp[1][1][1] = 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] + map[c[i - 1]][c[i]], dp[i][j][0]);
if (j >= 1)
{
dp[i][j][0] = min(dp[i - 1][j][0] + map[c[i - 1]][c[i]], dp[i - 1][j][1] + map[d[i - 1]][c[i]] * k[i - 1] + map[c[i - 1]][c[i]] * (1.0 - k[i - 1]));
dp[i][j][1] = min(dp[i][j][1],min(dp[i - 1][j - 1][0] + map[c[i - 1]][d[i]] * k[i] + map[c[i - 1]][c[i]] * (1.0 - k[i]), dp[i - 1][j - 1][1] + map[c[i - 1]][c[i]] * (1.0 - k[i - 1]) * (1.0 - k[i]) + map[c[i - 1]][d[i]] * (1.0 - k[i - 1]) * k[i] + map[d[i - 1]][c[i]] * k[i - 1] * (1 - k[i]) + map[d[i - 1]][d[i]] * k[i - 1] * k[i]));
}
}
ans = 1e30;
for (int i = 0; i <= m; i++)
ans = min(ans, min(dp[n][i][1], dp[n][i][0]));

printf("%.2lf", ans);
return 0;
}

posted @ 2017-07-28 23:30 zbtrs 阅读(...) 评论(...) 编辑 收藏