题意:在一个数组中找出两个不相交的串的的最大和。
解题思路:这是最大连续和的一个变形,不同之处就在于是求两个不相交的串的最大和。容易想到的就是用两个数组来分别记录以i结尾的串最大和和以i开头的最大和,然后固定一个前一个或后一个串,遍历另一个串,找出其中最大的,然后改变前一个串,再找最大的,依次比较最终就得到最大值了,这样做的时间复杂度为O(n2)。
但对于题目给的规模,这样的时间复杂度会超时。所以需要对思路进行改进。可以再用一个数组记录后一个(或前一个)中在i之后的串的最大值,这样固定前一个串时,后面一个串的最大值就可以直接取出,不用在遍历后面一个串了,时间复杂度为O(n)。
poj2593和这个问题一样,只是数据规模和输入输出格式不同,这里只给出poj2479的代码。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 50005;
int a[MAXN], f[MAXN], e[MAXN], me[MAXN];
int main()
{
int t, n, i, ans;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%d", &a[i]);
memset(me, 0, sizeof(me));
memset(f, 0, sizeof(f));
memset(e, 0, sizeof(e)); //虽然不需要对数组初始化,但这要形成习惯,避免以后出现问题。
f[0] = a[0];
e[n-1] = a[n-1];
me[n-1] = a[n-1];
for(i = 1; i < n; i++) //求以a[i]结尾的最大串
{
if(f[i-1] > 0)
{
f[i] = f[i-1]+a[i];
}
else
{
f[i] = a[i];
}
}
for(i = n-2; i > -1; i--) //求以a[i]开头的最大串,同时求出后i个数中的最大串
{
if(e[i+1] > 0)
{
e[i] = e[i+1]+a[i];
}
else
{
e[i] = a[i];
}
me[i] = max(me[i+1], e[i]); //记录后i个中最大的串。
}
//ans = 0; //这样初始化导致答案错误,因为ans可能小于0
ans = f[0]+me[1]; //初始化时最好是第一个可行值,防止上面的情况。
for(i = 0; i < n-1; i++)
{
ans = max(ans, f[i] + me[i+1]);
}
printf("%d\n", ans);
}
}