按蛋糕编号顺序累计每位朋友拿到的重量,达到 k 就开始下一组。
OJ: shumeng
题目 ID: CSP201703A
难度:入门
标签:模拟贪心
日期: 2026-07-31 16:21
形式化题目
有
思路
蛋糕的领取顺序完全由编号决定,朋友们只是被切分成连续的若干段,因此可以一趟扫描完成。
分组规则
把蛋糕序列切成尽量多的连续段,每段的总重量不小于
扫描累计
先看一个按题意逐朋友模拟的朴素写法:
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-31 16:21
* update_at: 2026-08-17 22:48
*/
// brute.cpp:按题意逐个朋友、逐块蛋糕模拟分配过程。
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
vector<int> cake(n + 1);
for (int i = 1; i <= n; i++) {
cin >> cake[i];
}
int position = 1;
int answer = 0;
while (position <= n) {
int current_weight = 0;
answer++;
while (position <= n && current_weight < k) {
current_weight += cake[position];
position++;
}
}
cout << answer << '\n';
return 0;
}正式实现不需要保存每一组。扫描每块蛋糕时维护当前朋友已拿到的重量 current_weight:
- 加入本块后若重量达到
,这位朋友结束,答案加一并把累计重量清零; - 若加入后仍不足
,继续为下一位朋友累计。
扫描结束后,若累计重量非零,说明还有一位朋友拿走了不足
代码
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-31 16:21
* update_at: 2026-08-17 22:48
*/
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
int current_weight = 0; // 当前这位朋友已拿到的总重量
int answer = 0;
for (int i = 1; i <= n; i++) {
int cake_weight;
cin >> cake_weight;
current_weight += cake_weight;
// 累计达到 k 后结束当前朋友,从下一位朋友重新开始累计
if (current_weight >= k) {
answer++;
current_weight = 0;
}
}
// 蛋糕全部分完时,最后一位朋友即使拿到的重量不足 k,也带走了剩余蛋糕
if (current_weight > 0) {
answer++;
}
cout << answer << '\n';
return 0;
}复杂度
- 时间:每块蛋糕只被处理一次,时间复杂度为
。 - 空间:只维护一个累计变量,额外空间复杂度为
。
总结
分组边界恰好是前缀和第一次达到