题目链接:http://poj.org/problem?id=2479
思路分析:假设数组为A[1, 2, …, n],则问题需要求数组A[s1, s1+1, …, t1]中的最大连续子段和与A[s2, …. , t2]中的最大连续子段和的和最大;
该问题实质上可以转换为求数组的最大子段和问题,只要预处理求出A[1, k]和A[k, n]数组的最大连续子段和,再枚举k的所有可能取值求
A[1, k]和A[k+1, n]中的最大连续子段和的和,再求出所有的情况中的最大值即可;
PS:在题目中s2不一定等于t1+1,但是要求出两个子段A[s1, .., t1]和A[s2, .., t2]中的最大连续子段和的和最大的情况,当s2 == t1+1时,
因为A[t1+1, …, t2]中的最大连续子段和必定大于等于A[s2, …, t2](s2>t1+1)中的最大连续子段和,所以A[s1, .., t1]与A[t1+1,…, t2]的最大连续子段
的和必定大于A[s1, …,t1]与A[s2, .., t2]最大连续子段的和,所以s2>t1+1的其他情况可以不必求解;
代码如下:
#include <cstdio> #include <iostream> using namespace std; const int MAX_N = 50000 + 10; int arr[MAX_N], dp_s[MAX_N], dp_r[MAX_N]; int arr_num; int main(int argc, char *argv[]) { int case_num, ans; scanf("%d", &case_num); while (case_num--) { int temp_ans, sum; scanf("%d", &arr_num); for (int i = 0; i < arr_num; ++i) scanf("%d", &arr[i]); temp_ans = INT_MIN, sum = 0; for (int i = 0; i < arr_num; ++i) { if (sum >= 0) sum += arr[i]; else sum = arr[i]; if (sum > temp_ans) temp_ans = sum; dp_s[i] = temp_ans; } temp_ans = INT_MIN, sum = 0; for (int i = arr_num - 1; i >= 0; --i) { if (sum >= 0) sum += arr[i]; else sum = arr[i]; if (sum > temp_ans) temp_ans = sum; dp_r[i] = temp_ans; } ans = dp_s[0] + dp_r[1]; for (int i = 1; i < arr_num - 1; ++i) { int sum = dp_s[i] + dp_r[i + 1]; if (sum > ans) ans = sum; } printf("%d\n", ans); } return 0; }