欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第1部分 基础算法(提高篇)--第1章- 贪心算法1428:数列分段

程序员文章站 2024-03-19 22:01:58
...

1428:数列分段

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 1193 通过数: 733
【题目描述】
对于给定的一个长度为N的正整数数列A[i],现要将其分成连续的若干段,并且每段和不超过M(可以等于M),问最少能将其分成多少段使得满足要求。

【输入】
第1行包含两个正整数N,M,表示了数列A[i]的长度与每段和的最大值;

第2行包含N个空格隔开的非负整数A[i],如题目所述。

【输出】
一个正整数,输出最少划分的段数。

【输入样例】
5 6
4 2 4 5 1
【输出样例】
3
【提示】
【数据范围】

对于20%的数据,有N≤10;

对于40%的数据,有N≤1000;

对于100%的数据,有N≤100000,M≤109,M大于所有数的最小值,A[i]之和不超过109。


思路:题目不可以打乱顺序,原数列是[ 4 2 4 5 1 ],划分为三段吼是 [ 4 2 ][ 4 ][ 5 1 ],我们先从第一个开始,当前状态标记为 b ,一开始,b=a[1],那么接下来从2开始枚举到n,如果当前状态加上一个数字仍然不超过最大限度m 的话,那就把这个数字加入当前状态,也就是不再开一个段数,否则就要新开一段了,同时重置状态s=a[ i ],最后ans要自加,因为一开始的第一个没有算进去.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,ans,b;
int a[100001];
int main(){
	scanf("%d%d",&n,&m);
	for(int i = 1; i <=n;i++)
	scanf("%d",&a[i]);
	b = a[n];
	for(int i = n - 1; i >= 1; i--)
	{
		if(b + a[i] <= m)//不超过最大限度m 的话,那就把这个数字加入当前状态
		b += a[i];
		else//新开一段了,同时重置状态b=a[ i ],ans要自加;
		{
			ans++;
			b = a[i];
		}
	}
	ans++;
	printf("%d",ans);
	return 0;
}