学术讨论,为什么分治递归求右边最大子列和就必须前进一步呢?
查看原帖
学术讨论,为什么分治递归求右边最大子列和就必须前进一步呢?
523439
ACDG楼主2021/7/7 14:47

注解满满,来讨论一下吧。为什么不能写solve(i,(i+j)/2)呢?如果写了某些情况会"无法求解",但我写了j==i+1时退出。我还尝试了写solve(i,(i+j)/2-1)测试点而出错。学术讨论,为什么分治递归求右边最大子列和就必须前进一步呢?

#include<iostream>
#include<algorithm>
using namespace std;
int a[200010];
int x;
int solve(int i, int j)//求i到j的最大和
{
    if(j==i+1)return max(a[j]+a[i],max(a[i],a[j]));
	if (i == j)return a[j];//如果序列长度唯一就直接返回唯一元素a[i]
	int left = solve(i, (i + j) / 2);//递归求左半部分的最大和
	int right = solve((i + j) / 2 , j);//递归求右半部分最大和

	int mid1 = -1e8, mid2 = -1e8, mid;//要初始化为负无穷大
	int sum = 0, k;
	for (k = (i + j) / 2 + 1; k <= j; k++)//记录从中间+1到右边的连续不间断序列最大和
	{
		sum += a[k];
		if (sum > mid2)mid2 = sum;
	}
	sum = 0;
	for (k = (i + j) / 2; k >= i; k--)//记录从中间到左边连续不间断序列最大和
	{
		sum += a[k];
		if (sum > mid1)mid1 = sum;
	}
	mid = mid1 + mid2;//合并为跨越中间的序列的最大和
	cout << "i:" << i << " j:" << j << " mid:" << mid << " left:" << left << " right:" << right << endl;
	return max(mid, max(left, right));//i到j的最大和 等于 i到中间序列的最大和 中间到j序列的最大和 跨越中间序列的最大和 的最大和
}
int main()
{
	int n;
	cin >> n;
	x = 1;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		if (a[i] >= 0)x = 0;
	}

	cout << solve(1, n);
	return 0;
}
2021/7/7 14:47
加载中...