Codeforces 1038D

题目链接:http://codeforces.com/problemset/problem/1038/D

题意:

给出 $n$ 个史莱姆,每个史莱姆有一个价值 $a[i]$,一个史莱姆可以吃掉相邻的史莱姆,此时其自身的价值就要减掉被吃掉的那个史莱姆的价值。

史莱姆会不断的互相吞噬直到最后只剩一个,要求你该史莱姆可能的最大价值。

题解:

相当于你在 $n$ 个数前面添加 $+$ 或者 $-$,然后拼成一个算式计算答案。

首先考虑到的是,史莱姆的价值是全正或者全负的情况,这样的话,不可能使得所有价值前都添上 $+$ 或者都添上 $-$,这个特判处理一下就好。

其次,就是有正有负的情况:

  首先,若仅有一个史莱姆身怀正价值,所以在它前面添上 $+$,其余所有史莱姆前面都添上 $-$,此时价值最大化;显然这是可行的,只要“正史莱姆”不停地吃掉相邻的所有“负史莱姆”即可。

  其次,若此时有两个“正史莱姆”,其余全是“负史莱姆”,那么通过一系列吞噬必然能够变成如下两种情况之一:

    “负史莱姆,正史莱姆,正史莱姆”:这种情况,要让两个正史莱姆的价值前面都是 $+$ 号,负史莱姆前面是个 $-$ 号,只需要让 $1$ 吃掉 $2$,再让 $3$ 吃掉 $1$ 即可。

    “正史莱姆,负史莱姆,正史莱姆”:这种情况,只需要让 $2$ 吃掉 $3$,再让 $1$ 吃掉 $2$ 即可。

  这样一来,两个正史莱姆的情况就能转化到一个正史莱姆的情况,以此类推,不难发现,三个正史莱姆可以转化到两个正史莱姆,……,$n$ 个正史莱姆可以转化到 $n-1$ 个正史莱姆。

所以,对于有正有负的情况,可以在所有正史莱姆前添 $+$ 号,所有负史莱姆前添 $-$ 号,即把所有史莱姆的价值的绝对值相加。因为不管怎么样,总有一个对应的吃法可以做到这样。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;
ll a[maxn];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    cin>>n;
    ll mx=-INF, mn=INF, sum=0;
    for(int i=1;i<=n;i++)
        cin>>a[i], sum+=abs(a[i]), mx=max(mx,a[i]), mn=min(mn,a[i]);

    if(n==1) {cout<<a[1]<<endl;return 0;}

    if(mx<0) //全负
        cout<<sum+2*mx<<endl;
    else if(mn>0) //全正
        cout<<sum-2*mn<<endl;
    else
        cout<<sum<<endl;
}

题解2:

当然,我们也可以不特判全正全负的情况,因为我们现在已经知道了,只要你确保既添加了 $+$ 号也添加了 $-$ 号,不管添加的正负号序列是怎么样的,都是通过某种吞吃方法来做到的。

所以我们可以用 $dp[i][x=0,1][y=0,1]$ 来表示,前 $i$ 个的最大值,$x$ 记录是否已经添加过 $+$ 号,$y$ 记录是否已经添加过 $-$ 号。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;
ll a[maxn],dp[maxn][2][2];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];

    if(n==1) {cout<<a[1]<<endl;return 0;}

    dp[1][1][0]=a[1], dp[1][0][1]=-a[1];
    dp[1][0][0]=dp[1][1][1]=-INF;
    for(int i=2;i<=n;i++)
    {
        dp[i][1][0]=dp[i-1][1][0]+a[i];
        dp[i][0][1]=dp[i-1][0][1]-a[i];

        dp[i][1][1]=-INF;
        dp[i][1][1]=max(dp[i][1][1],dp[i-1][0][1]+a[i]);
        dp[i][1][1]=max(dp[i][1][1],dp[i-1][1][0]-a[i]);
        dp[i][1][1]=max(dp[i][1][1],dp[i-1][1][1]+abs(a[i]));
    }

    cout<<dp[n][1][1]<<endl;
}
原文地址:https://www.cnblogs.com/dilthey/p/10492657.html