杭电-1003-max sum

博客

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;	 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eighteen Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值