HDOJ--1003 (最大子序列和)

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=1003

题解:

最开始题目都没看懂,看了别人的博客才知道这道题是要求最大子序列和。

这里我先归纳了三种求解最大子序列和问题的算法,在最后给出该题的AC代码。

方法1:暴力法 ( O(n^2) )

直接遍历所有可能的情况。

int maxSubSequence1(int arr[], int n)
{
	int max_sum = 0, sum;
	for (int i = 0; i < n; ++i) {
		sum = 0;
		for (int j = i; j < n; ++j) {
			sum += arr[j];
			if (sum > max_sum)
				max_sum = sum;
		}
	}
	return max_sum;
}

方法2:分治法( O(n*logn) )

若将一个序列从中分为两半的话,该序列的和最大的子序列的位置不外乎三种情况——左边的序列中、右边的序列中、横跨两个序列,所以这里可使用分治法来解决。

int maxSubSequence2(int arr[], int left, int right)
{
	if (left == right)
		if (arr[left] > 0)
			return arr[left];
		else
			return 0;

	int mid = (left + right) >> 1;
    // 获取左子序列中的最大子序列和
	int maxLeftSum = maxSubSequence2(arr, left, mid);
    // 获取右子序列中的最大子序列和
	int maxRightSum = maxSubSequence2(arr, mid + 1, right);


    // 获取横跨左右子序列的最大子序列之和
	int maxLeftBorderSum = 0, leftBorderSum = 0;
	for (int i = mid; i >= left; --i) {
		leftBorderSum += arr[i];
		if (leftBorderSum > maxLeftBorderSum)
			maxLeftBorderSum = leftBorderSum;
	}

	int maxRightBorderSum = 0, rightBorderSum = 0;
	for (int i = mid + 1; i <= right; ++i) {
		rightBorderSum += arr[i];
		if (rightBorderSum > maxRightBorderSum)
			maxRightBorderSum = rightBorderSum;
	}

    // 从三者中选出最大子序列的和
	return max3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum);
}

int max3(int a, int b, int c)
{
	if (a > b)
		return a > c ? a : c;
	else
		return b > c ? b : c;
}

方法3: 动态规划法 ( O(n) )

int maxSubSequence3(int arr[], int n)
{
	int sum = 0, max_sum = 0;
	for (int i = 0; i < n; ++i) {
		sum += arr[i];
		if (sum > max_sum)
			max_sum = sum;
		else if (sum < 0)
			sum = 0;
	}
	return max_sum;
}

 

AC代码:

#include <iostream>
using namespace std;

int main()
{
	//int maxSubSequence1(int arr[], int n);
	//int maxSubSequence2(int arr[], int left, int right);
	//int maxSubSequence3(int arr[], int n);
	//int max3(int a, int b, int c);

	int n_case;
	cin >> n_case;
	
	for (int j = 0; j < n_case; ++j) {
		int n, val, start, end, sum = 0, max_sum = -3000, tmp = 1;  // Damn 这个该死的max_sum!!!!!! 我之前初始值为0,结果一直AC不了
		start = end = 1;
		cin >> n;
		for (int i = 0; i < n; ++i) {
			cin >> val;
			sum += val;
			if (sum > max_sum) {
				max_sum = sum;
				start = tmp;
				end = i+1;
			}

			if (sum < 0){
				sum = 0;
				tmp = i + 2;
			}
		}
		// 5 1 -1 4 -5 3
		printf("Case %d:\n", j + 1);
		printf("%d %d %d\n", max_sum, start, end);
		if (j < n_case - 1)
			printf("\n");
	}
	
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值