csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:数列分段 Section I

csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:数列分段 Section I

题目描述

对于给定的一个长度为 N N N 的正整数数列 A i A_i Ai,现要将其分成连续 的若干段,并且每段和不超过 M M M(可以等于 M M M),问最少能将其分成多少段使得满足要求。

输入格式

第1行包含两个正整数 N , M N,M N,M,表示了数列 A i A_i Ai 的长度与每段和的最大值,第 2 2 2 行包含 N N N 个空格隔开的非负整数 A i A_i Ai,如题目所述。

输出格式

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

输入输出样例 1
输入 1
复制代码
5 6
4 2 4 5 1
输出 1
复制代码
3
说明/提示

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

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

对于 100 % 100\% 100% 的数据,有 N ≤ 10 5 , M ≤ 10 9 N≤10^5,M≤10^9 N≤105,M≤109, M M M 大于所有数的最大值, A i A_i Ai 之和不超过 10 9 10^9 109。

将数列如下划分:

4 \] \[ 24 \] \[ 51 \] \[4\]\[2 4\]\[5 1\] \[4\]\[24\]\[51

第一段和为 4 4 4,第 2 2 2 段和为 6 6 6,第 3 3 3 段和为 6 6 6 均满足和不超过 M = 6 M=6 M=6,并可以证明 3 3 3 是最少划分的段数。

思路分析

题目要求将正整数序列分成若干连续段,每段和不超过 (M),且段数最少。

贪心策略:从前往后遍历数列,维护当前段的和。若加上当前元素后段和超过 (M),则必须在此元素前切分,段数加一,并以此元素作为新段的开始;否则继续累加。

由于所有数均为正,贪心能保证局部最优(尽可能延长当前段),从而得到全局最优的最小段数。

时间复杂度 O(N),空间复杂度 O(1)。

代码实现

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main(){
    int n,m;cin>>n>>m; //n:数列长度,m:每段和上限
    int s=0,c=1;  //s:当前段和,c:段数(至少1段)
    for(int i=1;i<=n;i++){
        int x;cin>>x; //读入当前数
        if(s+x>m){ //若加入x会超过上限
            c++; //新开一段
            s=x;//新段起始和为x
        }else{
            s+=x; //继续累加
        }
    }
    cout<<c<<endl; 
    return 0;
}

功能分析

  • 输入处理:读取 (N) 和 (M),随后逐个读取数列元素。
  • 贪心模拟 :用变量 s 记录当前正在构建的段的和,c 记录已分好的段数。对于每个元素 x,判断 s + x > M 是否成立:
    • 成立:当前段无法再包含 x,故 c 自增,新段从 x 开始,s = x
    • 不成立:将 x 加入当前段,s += x
  • 边界处理 :初始 s=0c=1,保证第一个元素会被计入第一段;M 大于所有数的最大值,因此单个元素不会超过上限,保证算法可行。
  • 输出 :循环结束后,c 即为最少分段数。

各种学习资料,助力大家一站式学习和提升!!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"##########  一站式掌握信奥赛知识!  ##########";
	cout<<"#############  冲刺信奥赛拿奖!  #############";
	cout<<"######  课程购买后永久学习,不受限制!   ######";
	return 0;
}

【秘籍汇总】(完整csp信奥赛C++学习资料):

1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

https://edu.csdn.net/lecturer/7901 点击跳转

2、CSP信奥赛C++竞赛拿奖视频课:

https://edu.csdn.net/course/detail/40437 点击跳转

https://edu.csdn.net/course/detail/41081 点击跳转

3、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转

4、csp信奥赛冲刺一等奖有效刷题题解:

CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转

5、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转

· 文末祝福 ·

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"跟着王老师一起学习信奥赛C++";
	cout<<"    成就更好的自己!       ";
	cout<<"  csp信奥赛一等奖属于你!   ";
	return 0;
}
相关推荐
王老师青少年编程2 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:分糖果
c++·算法·贪心算法·csp·信奥赛·线性扫描贪心·分糖果
_日拱一卒2 小时前
LeetCode:2两数相加
算法·leetcode·职场和发展
py有趣2 小时前
力扣热门100题之零钱兑换
算法·leetcode
董董灿是个攻城狮2 小时前
Opus 4.7 来了,我并不建议你升级
算法
leaves falling2 小时前
C++模板进阶
开发语言·c++
无敌昊哥战神2 小时前
【保姆级题解】力扣17. 电话号码的字母组合 (回溯算法经典入门) | Python/C/C++多语言详解
c语言·c++·python·算法·leetcode
脱氧核糖核酸__2 小时前
LeetCode热题100——238.除了自身以外数组的乘积(题目+题解+答案)
数据结构·c++·算法·leetcode
再卷也是菜2 小时前
算法提高篇(1)线段树(上)
数据结构·算法
py有趣2 小时前
力扣热门100题之单词拆分
算法·leetcode