Description
Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:
d(A)=sum{a[s1]~a[t1]}+sum{a[s2]~a[t2]}
The rule is 1<=s1<=t1<s2<=t2<=n.
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.
自己写的程序(其实又给弄麻烦了,算法这块自己确实不行):
package OJ;
import java.util.*;
public class P9_temp {
public static void main(String[] args) {
class Find {
public int fromLtoR(List<Integer> al){
// int sum = 0;
int bigger = 0;
if(al.size()%2 == 0){ //大小为偶数
int i = 0;
int temp = 0;
while(i<al.size()){
temp += (al.get(i) + al.get(i+1));
if(temp > bigger)
bigger = temp;
i = i+2;
}
}
else { //大小为奇数
int i = 0;
int temp =0;
if(al.size() > 1){
while(i<al.size()-1){
temp += (al.get(i) + al.get(i+1));
if(temp > bigger)
bigger = temp;
i = i+2;
}
}
}
return bigger;
}
public int fromRtoL(List<Integer> al){
int bigger = 0;
if(al.size()%2 == 0){ //大小为偶数
int i = al.size()-1;
int temp = 0;
while(i > -1){
temp += (al.get(i) + al.get(i-1));
if(temp > bigger)
bigger = temp;
i = i-2;
}
}
else { //大小为奇数
int i = al.size()-1;
int temp =0;
if(al.size() > 1){
while(i>0){
temp += (al.get(i) + al.get(i-1));
if(temp > bigger)
bigger = temp;
i = i-2;
}
}
}
return bigger;
}
}
Scanner in = new Scanner(System.in);
int cases = in.nextInt();
for(int k=0; k<cases; k++){
int times = in.nextInt();
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(0);
for(int i=0; i<times; i++){
int temp = in.nextInt();
int longth = al.size() - 1;
if(al.get(longth) >= 0 && temp >= 0)
al.set(longth, al.get(longth)+temp);
else if(al.get(longth) <= 0 && temp <= 0)
al.set(longth, al.get(longth)+temp);
else
al.add(temp);
}
int big = 0;
int bigL = 0;
int bigger = 0;
int biggerL = 0;
for(int j=0; j<al.size(); j++){
if(j == 0){
big = al.get(j);
bigger = al.get(j);
bigL = j;
biggerL = j;
}
else{
if(al.get(j) >= bigger){
bigger = al.get(j);
biggerL = j;
}
else if(al.get(j) >= big){
big = al.get(j);
bigL = j;
}
}
}
Find f = new Find();
if(bigL > biggerL){//保证bigL < biggerL
int temp = biggerL;
biggerL = bigL;
bigL = temp;
}
if(bigL != biggerL){ //有两个最大值
int t1 = f.fromRtoL(al.subList(0, bigL));
int t3 = f.fromLtoR(al.subList(bigL+1, biggerL));
int t2 = f.fromRtoL(al.subList(bigL+1, biggerL));
int t4 = f.fromLtoR(al.subList(biggerL+1, al.size()));
int result = t1+t2+t3+t4+big+bigger;
System.out.println(result);
}
else { //有一个最大值
int t1 = f.fromRtoL(al.subList(0, bigL));
int t2 = f.fromLtoR(al.subList(bigL+1, al.size()));
int result = t1 + t2 + big;
System.out.println(result);
}
}
}
}
正确的算法:
在输入的同时,进行一次DP,计算出从左到右的最大值,并把它保存在数组dp的对应的下标元素中,这样之后,对于下标为i的元素,它其中保存的便是前面所 有元素可能的最大连续和。再从右到左进行一次DP,计算从右到左的最大连续和。假设此时已经算到下标为i的元素,那么将sum+dp[i-1]与ans进 行比较,将ans取较大者。最后当i到2的时候ans中的值即为所求的最大值。