codeforces1016C. Vasya And The Mushrooms(DP)

由于要访问每个格子刚好一次,所以只可能是一种情况,先上上下下访问然后再一直向右到达N处然后返回访问另一行未访问的格子,所以通过枚举开始一直向右走的起始位置可以得到结果。

终于在standing里面找到了一份能看懂的代码...orzAllunlimited大佬

其中f[i]表示,以第一行的第i个格子为时间零点,从第一行的第i个格子一直往右然后回到第二行的第i个格子的时间。

g[i]表示,以第二行的第i个格子为时间零点,从第二行的第i个格子一直往右然后回到第一行的第i个格子的时间。

f[i],g[i]都是通过倒推得到.

h[i]表示以上上下下的方式访问完前2*i个格子所花费的时间。

所以最后结果就是在h[i] + (i & 1 ? g[i + 1] : f[i + 1]) + (i * 2)*sum[i + 1]中取最大值

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 300005
#define ll long long
using namespace std;
ll n, a[N], b[N], sum[N], f[N], g[N], h[N];
int main()
{
    ll i, j, k, x, y, ans = 0;
    scanf("%I64d", &n);
    for (i = 1; i <= n; i++)scanf("%I64d", &a[i]);
    for (i = 1; i <= n; i++)scanf("%I64d", &b[i]);
    for (i = n; i >= 1; i--)sum[i] = sum[i + 1] + a[i] + b[i];
    for (i = n; i >= 1; i--)
    {
        f[i] = b[i] * (2 * (n - i) + 1) + sum[i + 1] + f[i + 1];
        g[i] = a[i] * (2 * (n - i) + 1) + sum[i + 1] + g[i + 1];
    }
    for (i = 1; i <= n; i++)
    {
        if (i & 1)h[i] = h[i - 1] + ((i - 1) * 2)*a[i] + ((i - 1) * 2 + 1)*b[i];
        else h[i] = h[i - 1] + ((i - 1) * 2 + 1)*a[i] + ((i - 1) * 2)*b[i];
    }
    for (i = 0; i <= n; i++)
        ans = max(ans, h[i] + (i & 1 ? g[i + 1] : f[i + 1]) + (i * 2)*sum[i + 1]);
    printf("%I64d\n", ans);
}

猜你喜欢

转载自blog.csdn.net/qq_37765455/article/details/81485422