一、题目大意
求连续的整数中两段不重叠的子串的最大值,运用动态规划可以很好地解决。
二、知识点回顾
先看看求一段子串的最大值是如何计算的。
读入的整数存在数组an中,设立新数组bn,b[i]存放以第i个元素结尾的子串的最大值,很显然,可以得出DP方程:b[i]=max(a[i],b[i-1]+a[i])
程序如下:
#include <iostream> using namespace std; #define MAX 1000 int main() { int t; cin>>t; int n; int a[MAX],b[MAX]; while(t--) { cin>>n; for (int i = 0; i <n ; ++i) { scanf("%d",&a[i]); } b[0] = a[0]; for (int j = 1; j <n ; ++j) { b[j] = max(a[j],b[j-1]+a[j]); } int max = -9999999; for (int k = 0; k <n ; ++k) { if (b[k]>max) max = b[k]; } cout << max << endl; } }
三、题目分析
除了源数据的数组a以外,设立三个数组,分别是b,c,d;
b[i]代表以b[i]元素结尾的前i+1个元素的最大和,c[i]代表以c[i]元素开始的最大元素和,d[i]用来保存第i+1个元素到最后一个元素的最大元素和,
最终结果就是b[i]+d[i+1]的最大值
代码如下:
#include <iostream> using namespace std; #define MAX 50010 int main() { int t; cin >> t; int n; int a[MAX], b[MAX], c[MAX], d[MAX]; while (t--) { scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d", &a[i]); } b[0] = a[0]; for (int j = 1; j < n; ++j) { b[j] = max(a[j], b[j - 1] + a[j]); } c[n - 1] = a[n - 1]; for (int k = n - 2; k > 0; k--) { c[k] = max(a[k], c[k + 1] + a[k]); } d[n - 1] = c[n - 1]; d[0] = 0; for (int l = n - 2; l > 0; l--) { d[l] = max(c[l], d[l + 1]); } int temp = -0x3f3f3f; for (int m = 0; m < n-1; m++) { temp = max(temp, d[m + 1] + b[m]); } printf("%d\n", temp); } }