题目: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 */