codeforces 1016C - Vasya And The Mushrooms 【构造 + 思维】

题目链接:戳这里

题意:从(1,1)出发,一遍把格子走完,每个格子只能走一次。问怎么走总和最大。

解题思路:画图可知,总共就3种走法的混合。

dw: 样例1的走法

up: 样例1反过来的走法

lp: 样例2的走法

两种组合情况:

先lp,后dw或up

我的思路是暴力预处理。把dw,up,lp三种走法先预处理出来,然后再看两种组合情况的拐点在哪,遍历拐点求出最大的值即可。虽然代码很长,但大多数都是重复代码,思路还是很简单的。

附ac代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <string>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 using namespace std;
10 typedef long long ll;
11 const int maxn = 1e6 + 10;
12 ll nu[3][maxn];
13 ll dw[3][maxn];
14 ll up[3][maxn];
15 ll lp[3][maxn];
16 ll sumup[3][maxn];//单纯的前缀和,用于处理混合情况时up里的时间
17 ll sumdw[3][maxn];//如上
18 int dx[6] = {1, 0,-1, 0};
19 int dy[6] = {0, 1, 0, 1};
20 int main(){
21     int n;
22     scanf("%d", &n);
23     for(int i = 1; i <= 2; ++i)
24     {
25         for(int j = 1; j <= n; ++j)
26         {
27             scanf("%lld", &nu[i][j]);
28         }
29     }
30     for(int i = 1; i <= n; ++i)
31     {
32         up[2][i] += nu[2][i] * i + up[2][i - 1];
33         sumup[2][i] += nu[2][i] + sumup[2][i - 1];
34     }
35     up[1][n] += up[2][n];
36     sumup[1][n] += sumup[2][n];
37     for(int i = n ; i >= 2; --i)
38     {
39         up[1][i] += nu[1][i] * (2 * n - i + 1) + up[1][i + 1];
40         sumup[1][i] += nu[1][i] + sumup[1][i + 1];
41     }
42     for(int i = 2; i <= n; ++i)
43     {
44         dw[1][i] += nu[1][i] * (i - 1) + dw[1][i - 1];
45         sumdw[1][i] += nu[1][i] + sumdw[1][i - 1];
46     }
47     dw[2][n] += dw[1][n];
48     sumdw[2][n] += sumdw[1][n];
49     for(int i = n; i >= 1; --i)
50     {
51         dw[2][i] += nu[2][i] * (2 * n - i) + dw[2][i + 1];
52         sumdw[2][i] += nu[2][i] + sumdw[2][i + 1];
53     }
54     int u = 1, v = 1;
55     int cnt = 0;
56     while(u <= 2 && v <= n)
57     {
58         for(int i = 0; i < 4; ++i)
59         {
60             ++cnt;
61             u += dx[i];
62             v += dy[i];
63             if(u > 2 || v > n) break;
64             lp[u][v] = lp[u - dx[i]][v - dy[i]] + nu[u][v] * cnt;
65         }
66     }
67     ll ans = 0;
68     for(int i = 1; i <= n; i += 2)
69     {
70         ans = max(ans, lp[1][i] + (i / 2 * 2) * (sumdw[2][i] - sumdw[1][i]) + dw[2][i] - dw[1][i]);//临界值不清楚的同学自己画图跑跑就知道啦
71     }
72     for(int i = 2; i <= n; i +=2)
73     {
74         ans = max(ans, lp[2][i] + (i - 2) * (sumup[1][i] - sumup[2][i]) + up[1][i] - up[2][i]);
75     }
76     printf("%lld\n", ans);
77     return 0;
78 }
View Code

猜你喜欢

转载自www.cnblogs.com/zmin/p/9435392.html