POJ2479&OpenJudge1481 Maximum sum

版权声明:本文原创如果喜欢,欢迎转载。^_^ https://blog.csdn.net/ccutyear/article/details/70232548

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=s2
Your 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.

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.


扫描二维码关注公众号,回复: 3049513 查看本文章

题意:给定一个数组在其中找出两个连续的子串,使得两个子串的和最大。

思路:对于前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代码和题解了。我看完后我发现我自己写的代码也不差啊!!!\(^-^)/

猜你喜欢

转载自blog.csdn.net/ccutyear/article/details/70232548