P1115 最大子段和 题解

  • C++ 实现
// -*- coding: utf-8 -*-
//  @ Date   : 2020/5/20 13:14
//  @ Author : RichardLau_Cx
//  @ file   : Richard.cpp
//  @ IDE    : Dex-C++
//  @ Source : luogu

// 算法思想:分治法 

#include <iostream> 

using namespace std;


int maxSum(int *sequence, int x, int y)
{
	int L, R, v, m;
	
	// 第一步:划分问题
	m = (x + y) / 2;  // 单纯的"/"号是朝零方向的取整,而不是向下取整,如:5/2=2, -5/2=-2
//	m = x + (y - x) / 2;
	
	// 第二步:递归求解 
	if (y - x == 1)
	{  // 递归出口 
		return sequence[x];
	 } 
	
	int maxs = max(maxSum(sequence, x, m), maxSum(sequence, m, y));
	
	// 当前左子序列总和 
	v=0;  
	L = sequence[m-1];
	for (int i=m-1; i >= x; i--)
	{
		L = max(L, v += sequence[i]);   // 相当于每加一次,就进行一次比较 
	 } 
	 
	// 当前右子序列总和
	v=0; 
	R = sequence[m];
	
	for (int i=m; i < y; i++) 
	{
		R = max(R, v += sequence[i]);
	 } 
	
	// 第三步,合并问题 
	return max(maxs, R+L);
}


int main()
{	
 	// 对于100%的数据,保证:1 <= n <= 2 * 10^5,-10^4 <= ai <= 10^4; 
	int n;  // 序列长度
	
	cin >> n;
	
	int sequence[n]; 
	
	for (int i=0; i < n; i++)
	{
//		scanf("%d", &sequence[i]);
		cin >> sequence[i];
	}
	
//	cout << "maxSum(sequence, 0, n): " << maxSum(sequence, 0, n);
	cout << maxSum(sequence, 0, n) << endl;
	
	/*
	for (int i=0; i < n; i++)
	{
//		printf("%d ", sequence[i]);
		cout << sequence[i] << ' ';
	}
	*/
	
	return 0;
}
  • 测试代码
// -*- coding: utf-8 -*-
//  @ Date   : 2020/5/20 13:14
//  @ Author : RichardLau_Cx
//  @ file   : Richard.cpp
//  @ IDE    : Dex-C++
//  @ Source : 紫书-P223

#include <iostream>

using namespace std;

int maxSum(int *A, int x, int y);

int main()
{
	int array[] = {2, -4, 3, -1, 2, -4, 3};  // 传入数列,数组的索引是从零开始的 
	int x = 0;  // 子段左边界 
	int y = 6;  // 子段右边界 
	
	cout << "maxSum(array, x, y): " << maxSum(array, x, y) << endl;
	
	return 0;
 } 
 
 
int maxSum(int *A, int x, int y)
{  // 返回数组在左闭右开区间 [x, y) 中的最大连续和 
	int v;  // 当前值之和 
	int L;  // 左边的最大连续和 
	int R;  // 右边的最大连续和
	int maxs;  // 左右边合并起来的最大值 
	
	if (y - x == 1)   // 递归出口 
	{  // 因为区间右开,所以只剩下了x(左边),直接返回值 
		return A[x];
	}
	
	int m = x + (y - x) / 2;  // 分治第一步:划分成 [x, m) 和 [m, y),m刚好为x和y的中间点 
	maxs = max(maxSum(A, x, m), maxSum(A, m, y));  // 分治第二步:递归求解 
//	int v, L, R;
	
	v = 0;
	L = A[m-1];  // 分治第三步:合并(1) --- 从分界点开始,往左的最大连续和-L 
	
	for (int i = m-1; i >= x; i--) 
	{
		L = max(L, v += A[i]);  // 从当前中点,向左延伸找左边的最大连续和 
	}
	
	v = 0;
	R = A[m];  // 分治第三步:合并(2) --- 从分界点开始,往右的最大连续和-R 
	
	for (int i = m; i < y; i++)
	{
		R = max(R, v += A[i]);  // 从当前中点,向右延伸找右边的最大连续和 
	 } 
	 
	return max(maxs, L+R);  // 把子问题的解,与当前L与R的和做比较 
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值