【来源】
一本通题库-1428
LibreOJ-10006
vjudge
【题目描述】
对于给定的一个长度为 N N N的正整数数列 A [ i ] A[i] A[i],现要将其分成连续的若干段,并且每段和不超过 M M M(可以等于 M M M),问最少能将其分成多少段使得满足要求。
【输入格式】
第1行包含两个正整数 N N N, M M M,表示了数列 A [ i ] A[i] A[i]的长度与每段和的最大值;
第2行包含 N N N个空格隔开的非负整数 A [ i ] A[i] A[i],如题目所述。
【输出格式】
一个正整数,输出最少划分的段数。
【输入样例】
5 6
4 2 4 5 1
【输出样例】
3
【数据范围】
对于 20 20 20%的数据,有 N ≤ 10 N≤10 N≤10;
对于 40 40 40%的数据,有 N ≤ 1000 N≤1000 N≤1000;
对于 100 100 100%的数据,有 N ≤ 100000 N≤100000 N≤100000, M ≤ 1 0 9 M≤10^9 M≤109,M大于所有数的最小值, A [ i ] A[i] A[i]之和不超过 1 0 9 10^9 109。
【解析】
一题比较简单的贪心。
可以说这是一题模拟题。
- 判断a[i]的值加起来是否比m大
- 判断如果加起来比m大,ans++
- 判断最后的单独一组
就是这么简单。
这里给出了两种写法,都是对的。
【代码1】
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
const int N=1e5+5;
int n,m;
int a[N];
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
int sum=0,ans=0;
for(int i=1; i<=n; i++) {
if(sum+a[i]>m) {
sum=a[i];
ans++;
} else sum+=a[i];
}
if(sum!=0) ans++;
printf("%d\n",ans);
return 0;
}
【代码2】
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
const int N=1e5+5;
int n,m;
int a[N];
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
int sum=0,ans=1;
for(int i=1; i<=n; i++) {
if(sum+a[i]>m) {
sum=a[i];
ans++;
} else sum+=a[i];
}
printf("%d\n",ans);
return 0;
}