博客
Max Sum
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 324665 Accepted Submission(s): 77206
Problem Description
Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
Output
For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.
Sample Input
2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5
Sample Output
Case 1: 14 1 4
Case 2: 7 1 6
code:
这是我刚开时只考虑暴力解决的办法,思路就是找出所有的子序列的值,然后进行比较记录,没有意外的超时了。
#include<stdio.h>
#include<math.h>
int sumNumber(long arr[100000], int s, int e) {
int sumN = 0;
for(int i = s; i <= e; i++) {
sumN+=arr[i];
}
return sumN;
}
int main() {
int L;
int l = 1;
int n;
long numArr[100000];
long numChart[100000][100000]
int start, end, sum;
scanf("%d", &L);
while(L--) {
int start = 1, end = 1, sum=-1001;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &numArr[i]);
}
for (int i = 0; i < n; i++) {
for (int j = 1; (j+i) <= n; j++) {
if (sum < sumNumber(numArr, j, j+i)) {
sum = sumNumber(numArr, j, j+i);
start = j;
end = i + j;
} else if (sum == sumNumber(numArr, j, j+i)) {
if (end > j+i) {
end = i + j;
start = j;
}
if (start > j) {
end = i + j;
start = j;
} else if (start == j) {
if (end < i+j) {
end = i + j;
}
}
}
}
}
printf("Case %d:\n", l);
printf("%d %d %d\n\n", sum, start, end);
l++;
}
return 0;
}
这是改过之后的代码:
思路是:我们输入的序列,从头开始相加,start的值是1,只有当前面的序列值为负数的时候可以直接抛弃掉,因为负值越加越少,所以可以从头开始记录,这个时候序列从0重新计算。
假设极端情况,序列中都是正数,那么我们只需要依次相加就可以了。
但是序列中存在负数,那么我们就需要考虑寻找最大和的过程中,前面遍历过的和是负数的话,反而会使后面的和变小,所以直接舍弃。
在寻找最大值的过程中一直记录当前已知的最大值。最后输出。
我们需要清除的一点是,计算过程中子序列的起始值是可能会变化的,而不是一直从头,我们得到的和也不是从头开始的。所记录的最大值一直是i之前的序列子序列的最优解。
#include<stdio.h>
#include<math.h>
int main() {
int L;
int l = 1;
int n;
long numArr[100000];
int start, end, sum, max, s;
scanf("%d", &L);
while(L--) {
start = 1; s = 1, end = 1; sum=0; max=-1001;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &numArr[i]);
sum += numArr[i];
if (sum > max) {
max = sum;
end = i;
start = s;
}
if (sum < 0) {
sum = 0;
s = i+1;//只有当i之前的值小于零,子序列的起始值才会发生变化。2
}
}
printf("Case %d:\n", l);
printf("%d %d %d\n", max, start, end);
if (L > 0) {
printf("\n");
}
l++;
}
return 0;
}