第五周 8.7-8.13

有做题 没空写博客。

8.8

CF 704 B - Ant Man

由于左右代价不一样,直接拆绝对值。

那么代价只和每个点的入边与出边是向左还是向右有关。

考虑dp[i][j][k][l]为前i个点,有j个剩一个出度一个入度的联通块,k个只有一个入度的联通块,l个只有出度的联通块。

对于每个点,枚举它的出边与入边是向左还是向右,一共四种情况。

需要注意以下几点:

1.第一维可以滚动;k和l最大只有1,即为s和e所在的联通块,3、4维压一起更好写。

2.s和e只有一条边,所以要单独考虑。

3.不能让前面的联通块自己成环封闭起来,所以每次dp只能用至少含有一条出边或者入边的状态。

4.每次加边要考虑各种情况,比如是加在含有一出一入的联通块上,还是加在只有一入的联通块上,当然得保证前面的状态含有这样的联通块才能加。

总之细节很多,调了好久都快弃了竟然过了感动哭了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const LL INF = 1e18;
 8 LL dp[5005][4], cpy[5005][4];
 9 LL x[5005], a[5005], b[5005], c[5005], d[5005];
10 
11 int main(void)
12 {
13     int n, s, e;
14     scanf("%d %d %d", &n, &s, &e);
15     for(int i = 1; i <= n; i++) scanf("%I64d", x + i);
16     for(int i = 1; i <= n; i++) scanf("%I64d", a + i);
17     for(int i = 1; i <= n; i++) scanf("%I64d", b + i);
18     for(int i = 1; i <= n; i++) scanf("%I64d", c + i);
19     for(int i = 1; i <= n; i++) scanf("%I64d", d + i);
20 
21     for(int i = 0; i <= n; i++)
22     for(int j = 0; j < 4; j++) dp[i][j] = INF;
23     dp[0][0] = 0;
24 
25     for(int i = 1; i <= n; i++)
26     {
27         memcpy(cpy, dp, sizeof(cpy));
28         for(int j = 0; j <= n; j++)
29         for(int k = 0; k < 4; k++) dp[j][k] = INF;
30 
31         for(int j = 0; j <= n; j++)
32         for(int k = 0; k < 4; k++)
33         {
34             if(cpy[j][k] == INF) continue;
35             if(i > 1 && !j && !k) continue;
36 
37             if(i == s)
38             {
39                 dp[j][k^1] = min(dp[j][k^1], cpy[j][k] + d[i] - x[i]);
40                 if(k & 2) dp[j][k^2] = min(dp[j][k^2], cpy[j][k] + c[i] + x[i]);
41                 if(j) dp[j-1][k^1] = min(dp[j-1][k^1], cpy[j][k] + c[i] + x[i]);
42             }
43 
44             else if(i == e)
45             {
46                 dp[j][k^2] = min(dp[j][k^2], cpy[j][k] + b[i] - x[i]);
47                 if(k & 1) dp[j][k^1] = min(dp[j][k^1], cpy[j][k] + a[i] + x[i]);
48                 if(j) dp[j-1][k^2] = min(dp[j-1][k^2], cpy[j][k] + a[i] + x[i]);
49             }
50 
51             else
52             {
53                 dp[j+1][k] = min(dp[j+1][k], cpy[j][k] + b[i] + d[i] - x[i] - x[i]);
54                 if(j || (k & 1)) dp[j][k] = min(dp[j][k], cpy[j][k] + a[i] + d[i]);
55                 if(j || (k & 2)) dp[j][k] = min(dp[j][k], cpy[j][k] + b[i] + c[i]);
56                 if(j) dp[j-1][k] = min(dp[j-1][k], cpy[j][k] + a[i] + c[i] + x[i] + x[i]);
57                 if(k == 3) dp[j][k^3] = min(dp[j][k^3], cpy[j][k] + a[i] + c[i] + x[i] + x[i]);
58             }
59         }
60     }
61     printf("%I64d\n", dp[0][0]);
62     return 0;
63 }
Aguin

 

posted @ 2016-08-08 21:57  Aguin  阅读(216)  评论(0编辑  收藏  举报