[NOIP 2016] 换教室

嘟嘟嘟

这道题很显然是dp,刚开始我是设dp[i][j]表示到第 i 个时间段,申请了 j 个课程耗费的体力值的总和的最小期望值,但是想了半天也没有推出转移方程,现在想想觉得应该是无法表示他第 i 时刻在哪一个教室。

于是我们加一维dp[i][j][0/1]表示第 i 时刻我们是否申请了换教室。那么dp方程就很好推出来了:

先令u1 = c[i - 1], v1 = c[i], u2 = d[i - 1], v2 = d[i]

dp[i][j][0] = min(dp[i - 1][j][0] + v[u1][v1], dp[i - 1][j][1] + v[u2][v1] * k[i - 1] + v[u1][v1] * (1 - k[i - 1]))

dp[i][j][1] = min(dp[i - 1][j - 1][0] + v[u1][v2] * k[i] + v[u1][v1] * (1 - k[i]),

       dp[i - 1][j - 1][1] + v[u2][v2] * k[i - 1] * k[i] + v[u1][v2] * (1 - k[i - 1]) * k[i] + v[u2][v1] * k[i - 1] * (1 - k[i]) + v[u1][v1] * (1 - k[i - 1]) * (1 - k[i]))

总的来说,就是如果这一次申请换教室的话,要同时考虑换教室成功和不成功的两种情况。

然后ans = min(dp[n][i][0], dp[n][i][1]) (0 <= i <= m,因为可以不申请换任何一个教室)

然后求多源最短路,又因为V <= 300,直接floyd预处理就行。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a) memset(a, 0, sizeof(a))
15 typedef long long ll;
16 typedef double db;
17 const int INF = 0x3f3f3f3f;
18 const db eps = 1e-8;
19 const int max_nod = 305;
20 const int maxn = 2e3 + 5;
21 inline ll read()
22 {
23     ll ans = 0;
24     char ch = getchar(), last = ' ';
25     while(!isdigit(ch)) {last = ch; ch = getchar();}
26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
27     if(last == '-') ans = -ans;
28     return ans;
29 }
30 inline void write(ll x)
31 {
32     if(x < 0) x = -x, putchar('-');
33     if(x >= 10) write(x / 10);
34     putchar(x % 10 + '0');
35 }
36 
37 int n, m, V, E;
38 ll v[max_nod][max_nod]; 
39 int a[maxn], b[maxn];
40 db p[maxn];
41 db dp[maxn][maxn][2];
42 
43 void init()
44 {
45     for(int i = 1; i <= V; ++i)
46         for(int j = 1; j <= V; ++j) v[i][j] = INF;
47     for(int i = 1; i <= n; ++i)
48         for(int j = 0; j <= m; ++j) dp[i][j][0] = dp[i][j][1] = INF;        //j:0开始 
49 }
50 
51 int main()
52 {
53     n = read(); m = read(); V = read(); E = read();
54     for(int i = 1; i <= n; ++i) a[i] = read();
55     for(int i = 1; i <= n; ++i) b[i] = read();
56     for(int i = 1; i <= n; ++i) scanf("%lf", &p[i]);
57     init();
58     for(int i = 1; i <= E; ++i)
59     {
60         int x = read(), y = read(); ll co = read();
61         v[x][y] = v[y][x] = min(v[x][y], co);
62     }
63     for(int k = 1; k <= V; ++k)
64         for(int i = 1; i <= V; ++i)
65             for(int j = 1; j <= V; ++j)
66                 v[i][j] = min(v[i][j], v[i][k] + v[k][j]);
67     for(int i = 1; i <= V; ++i) v[i][i] = v[i][0] = v[0][i] = 0;
68     dp[1][0][0] = dp[1][1][1] = 0;
69     for(int i = 2; i <= n; ++i)
70     {
71         dp[i][0][0] = dp[i - 1][0][0] + v[a[i - 1]][a[i]];
72         for(int j = 1; j <= min(i, m); ++j)
73         {
74             db tp_0 = dp[i - 1][j][0] + v[a[i - 1]][a[i]];
75             db tp_1 = dp[i - 1][j][1] + (db)v[b[i - 1]][a[i]] * p[i - 1] + (db)v[a[i - 1]][a[i]] * (1 - p[i - 1]);
76             dp[i][j][0] = min(dp[i][j][0], min(tp_0, tp_1));
77             tp_0 = dp[i - 1][j - 1][0] + (db)v[a[i - 1]][b[i]] * p[i] + (db)v[a[i - 1]][a[i]] * (1 - p[i]);
78             tp_1 = dp[i - 1][j - 1][1] + (db)v[b[i - 1]][b[i]] * p[i - 1] * p[i] + (db)v[a[i - 1]][b[i]] * (1 - p[i - 1]) * p[i];
79             tp_1 += (db)v[b[i - 1]][a[i]] * p[i - 1] * (1 - p[i]) + (db)v[a[i - 1]][a[i]] * (1 - p[i - 1]) * (1 - p[i]);
80             dp[i][j][1] = min(dp[i][j][1], min(tp_0, tp_1));
81         }
82     }
83     db ans = INF;
84     for(int i = 0; i <= m; ++i) ans = min(ans, min(dp[n][i][0], dp[n][i][1]));
85     printf("%.2lf\n", ans);
86     return 0;
87 }
View Code

猜你喜欢

转载自www.cnblogs.com/mrclr/p/9634750.html