Maximum sum
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 40603 | Accepted: 12667 |
Description
Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:
t1 t2 d(A) = max{ ∑ai + ∑aj | 1 <= s1 <= t1 < s2 <= t2 <= n } i=s1 j=s2Your task is to calculate d(A).
Input
The input consists of T(<=30) test cases. The number of test cases (T) is given in the first line of the input.
Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, ..., an. (|ai| <= 10000).There is an empty line after each case.
Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, ..., an. (|ai| <= 10000).There is an empty line after each case.
Output
Print exactly one line for each test case. The line should contain the integer d(A).
Sample Input
1 10 1 -1 2 2 3 -3 4 -4 5 -5
Sample Output
13
Hint
In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer.
Huge input,scanf is recommended.
Huge input,scanf is recommended.
题意:给定一个数组在其中找出两个连续的子串,使得两个子串的和最大。
思路:对于前j个元素,可以将它分为两个子串,也可以将它分为一个子串。则:对于DP[1][j]和DP[2][j]的含义分别为“对于前j个元素分为一个以第j个元素结尾的连续子串和”和“对于前j个元素分为两个以第j个元素结尾的连续子串和。”那么DP[1][j]和DP[2][j]的动态转移方程式分别是DP[1][j] = DP[1][j - 1] > 0 ? DP[1][j] : 0 + num[j] 、(num[j]表示为数组中的第j个元素。) DP[2][j] = max(DP[2][j - 1],DP[1][0],DP[1][1],DP[1][2],DP[1][3].......DP[1][j-2],DP[1][1]) + num[j]。
根据这个思路可以写出的AC代码如下:
#include<iostream>
#include<cmath>
#include<cstring>
#define INF 10005
#define MAX 50005
using namespace std;
int num[MAX];
int DP[3][MAX];
int main( )
{
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
memset(DP,0,sizeof(DP));
int max_DP1;
for(int j = 0; j < n; j++)
scanf("%d",&num[j]);
DP[1][0] = num[0];
DP[2][0] = num[0];
max_DP1 = num[0];
for(int j = 1; j < n; j++){
DP[1][j] = (DP[1][j-1] > 0 ? DP[1][j-1] : 0) + num[j]; //两个动态转移方程式
DP[2][j] = max(max_DP1 + num[j],DP[2][j-1] + num[j]);
max_DP1 = max(max_DP1,DP[1][j]); //在max_DP1中记录的就是DP[1][0],DP[1][1],DP[1][2],DP[1][3].......DP[1][j-2],DP[1][1]中的最大值。
}
int ans = -INF;
for(int j = 1; j < n; j++){
ans = max(ans,DP[2][j]);
}
/*for(int j = 0; j < n; j++)
cout << DP[1][j] << "/" << DP[2][j] << endl; */
cout << ans << endl;
}
}
然后,这个思路在空间上可以直接优化为几个变量。
优化后的AC代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#define INF 10005
#define MAX 50005
using namespace std;
int num[MAX];
int DP1,DP2;
int main( )
{
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
int max_DP1,ans = -INF;
int a;
scanf("%d",&a);
DP1 = DP2 = max_DP1 = a;
for(int j = 1; j < n; j++){
scanf("%d",&a);
DP1 = (DP1 > 0 ? DP1 : 0) + a;
DP2 = max(max_DP1 + a,DP2 + a);
max_DP1 = max(max_DP1,DP1);
ans = max(ans,DP2);
}
cout << ans << endl;
}
}
用我这个思路写的代码在POJ上如果使用cin提交的话会超时必须要使用scanf,如果是在OpenJudge上 的话用cin可以提交。
这个题在网上其实已经有很多AC代码和题解了。我看完后我发现我自己写的代码也不差啊!!!\(^-^)/