最大字段和

博客围绕最大字段和问题展开,给定由n个整数组成的序列,要选取相邻一段使其和最大。介绍了建立递归关系,当b[j - 1]>0时,b[j]=b[j - 1]+a[j],否则b[j]=a[j],还给出了状态转移方程,最后提及最大子矩阵和问题是其推广。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给定由n个整数(可能有负数)组成的序列a1,a2,...,an,要在这n个数中选取相邻的一段ai,ai+1,...,aj(1≤i≤j≤n),使其和最大,输出最大的和。当所有整数均为负整数时,定义最大字段和为0。n个整数(可能有负数)组成的序列a_1,a_2,...,a_n,要在这n个数中选取相邻的一段a_i,a_{i+1},...,aj(1\leq i \leq j \leq n),使其和最大,输出最大的和。当所有整数均为负整数时,定义最大字段和为0。n()a1,a2,...,an,naiai+1,...,aj1ijn,使0
例如,当{a1,a2,...,a8}\{a_1,a_2,...,a_8\}{a1,a2,...,a8} = {1,-3,7,8,-4,12,-10,6}时,最大字段和为23。令 b[j]=max⁡1≤i≤j{∑k=ija[k]}(1≤j≤n),b[j] =\max_{1 \leq i \leq j} \{ \sum_{k=i}^j a[k]\} (1 \leq j \leq n),b[j]=1ijmax{k=ija[k]}(1jn),则所求的最大字段和为:
max⁡1≤i≤j≤n{∑k=ija[k]}==max⁡1≤j≤n{max⁡1≤i≤j{∑k=ija[k]}}=max⁡1≤j≤n{b[j]}\max_{1 \leq i \leq j \leq n} \{ \sum_{k=i}^j a[k]\} == \max_{1 \leq j \leq n} \{ \max_{1 \leq i \leq j} \{\sum_{k=i}^j a[k]\} \} = \max_{1 \leq j \leq n} \{ b[j]\}1ijnmax{k=ija[k]}==1jnmax{1ijmax{k=ija[k]}}=1jnmax{b[j]}
其实上面定义看不懂并不影响理解,看懂下面的递归关系即可,上面写着只是为了显得更专业,好吧!我承认是课本的定义。

建立递归关系

b[j−1]>0时,b[j]=b[j−1]+a[j],否则b[j]=a[j]。b[j-1]>0时,b[j] = b[j-1]+a[j],否则b[j] = a[j]。b[j1]>0b[j]=b[j1]+a[j],b[j]=a[j]这句话还是十分简单的,要是前面的和大于0,那最大和一定要加上前面的正数。反之,若小于0则必须弃之。
b[j]状态转移方程为:
b[j]=max⁡{b[j−1]+a[j],a[j]},(1≤j≤n)b[j] =\max \{ b[j-1] + a[j],a[j] \}, (1 \leq j \leq n)b[j]=max{b[j1]+a[j],a[j]},(1jn)

代码

#include <stdio.h>

#define NUM 1001
int a[NUM];
int MaxSum(int n, int &besti, int &bestj)
{
	int sum=0; 
	int b=0;
	int begin = 0;//当b[i-1]小于等于0时,记录b[i]=a[i]的位置 
	for (int i = 1;i <= n;i++)
	{
		if (b>0) b+=a[i]; //状态转移方程 
		else {//当b<0时,更新到最新的位置 
			b=a[i];
			begin = i;//开始位置 
		}
		if (b>sum) 
		{
			sum = b; //更新最优值 
			besti = begin; 
			bestj = i;
		}
	}
	return sum;
}

int main() 
{
	int n;
	int besti, bestj;
	while (scanf("%d", &n) && n) 
	{
		besti = 0; //初始化开头 
		bestj = 0; //初始化结尾 
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		printf("%d\n", MaxSum(n, besti, bestj));//输出最优值 
		printf("From %d to %d\n", besti, bestj);//输出最优解 
	}
	return 0;
}

输入

8
1 -3 7 8 -4 12 -10 6
0

输出

23
From 3 to 6

总结

最大子矩阵和问题是最大字段和问题的推广,首先在这埋下一个坑,日后若遇到在加以学习吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值