第五周 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 }