CodeForces

题目:https://codeforces.com/problemset/problem/1038/D

题意:给你n个数字,每个数字可以吃左右两边的数,然后吃完后自己变成 a[i]-a[i+1]或者a[i]-a[i-1],然后问你最后只剩一个数的时候最大可能的值是多少

思路:我们首先想是由哪一个数会留到最后,那他肯定会吃掉左边的数和右边的数,而如果要使当前数字尽量大,那么就要使左右两边的数字尽量小,我们要确定左边右边的数字尽量小的话,因为有负数的关系,我们每一步都要记录当前格子从左到右的最大值和最小值,然后同理再记录一个从右到左的,然后枚举哪一个留到最后,减去前缀最小和后缀最小即可

#include<bits/stdc++.h>
#define maxn 500005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll n,a[maxn];
ll dp1[maxn][2];
ll dp2[maxn][2];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int q;
    dp1[n][0]=a[n];dp1[n][1]=a[n];
    dp2[1][0]=a[1];dp2[1][1]=a[1];
    for(int i=n-1;i>=2;i--){
        dp1[i][0]=max(max(a[i]-dp1[i+1][1],a[i]+dp1[i+1][0]),dp1[i+1][0]-a[i]);
        dp1[i][1]=min(min(a[i]-dp1[i+1][0],a[i]+dp1[i+1][1]),dp1[i+1][1]-a[i]);
    }
    for(int i=2;i<=n-1;i++){
        dp2[i][0]=max(max(a[i]-dp2[i-1][1],a[i]+dp2[i-1][0]),dp2[i-1][0]-a[i]);
        dp2[i][1]=min(min(a[i]-dp2[i-1][0],a[i]+dp2[i-1][1]),dp2[i-1][1]-a[i]);
    }
    ll mx=a[1]-dp1[2][1];
    for(int i=2;i<=n;i++){
        mx=max(mx,a[i]-dp1[i+1][1]-dp2[i-1][1]);
    }
    cout<<mx;
}
/*
5
-14 -2 0 -19 -12
47
*/
原文地址:https://www.cnblogs.com/Lis-/p/11396298.html