POJ2479&OpenJudge1481 Maximum sum

来源:互联网 发布:mysql中删除一个字段 编辑:程序博客网 时间:2024/05/16 08:12

Maximum sum
Time Limit: 1000MS Memory Limit: 65536KTotal 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

1101 -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.


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

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

0 0
原创粉丝点击