最大字段和

这篇博客介绍了如何解决寻找序列中连续子段最大和的问题,分别展示了暴力求解、前缀和优化、动态规划和贪心算法四种方法。动态规划方法通过状态转移方程f[i]=max(f[i−1]+a[i],a[i])实现,而贪心算法则根据当前数与前缀和的关系判断是否加入序列。

给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。

暴力解法:

int n;
int a[200000 + 10];

int main(){
	cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
	}
	
	int ans = -1;
	
	for(int i = 1; i <= n; i++){
		for(int j = i; j <= n; j++){
			
			int summ = 0;
			
			for(int k = i; k <= j; k++){
				summ += a[k];
			}
			
			ans = max(summ, ans);
		}
	}
	
	cout << ans;
	
	return 0;
}

前缀和优化:

int n;
int a[200000 + 10];
int s[200000 + 10];

int main(){
	cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
		s[i] = s[i - 1] + a[i];
	}
	
	int ans = -1;
	
	for(int i = 1; i <= n; i++){
		for(int j = i; j <= n; j++){
			
			ans = max(s[j] - s[i - 1], ans);
			
		}
	}
	
	cout << ans;
	
	return 0;
}

动规:

第一个数为一个有效序列
如果一个数加上上一个有效序列得到的结果比这个数大,那么该数也属于这个有效序列。
如果一个数加上上一个有效序列得到的结果比这个数小,那么这个数单独成为一个新的有效序列

状态转移方程:f[i]=max(f[i−1]+a[i],a[i])f[i] = max(f[i - 1] + a[i], a[i])f[i]=max(f[i1]+a[i],a[i])

在计算过程中记录max就好了

#include <iostream>
#include <cstdio>
#include <algorithm>

#define endl "\n"

using namespace std;

int n;
int a[200000 + 10];
int f[200000 + 10];

int main(){
	cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
	}
	
	int ans = -100000;
	
	for(int i = 1; i <= n; i++){
		f[i] = max(f[i - 1] + a[i], a[i]);
		ans = max(f[i], ans);
	}
	
	cout << ans;
	
	return 0;
}

贪心

如果前面一段数的和是负数了,那么下一个数也没有必要需要前面的数来构成最大值了,因为会变小

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int n;
int a[200009];
int sum;

int main(){
	cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
	} 
	for(int i = 1; i <= n; i++){
		
		if(sum < 0) sum = 0;
		sum += a[i];
		ans = max (ans, sum);
	}
	cout << ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值