二分最大月度开销,用一次贪心扫描统计所需财政周期数。
OJ: noi_openjudge
题目 ID: ch0111-06
难度:普及+/提高
标签:二分贪心python
日期: 2026-07-30 23:01
题意
将连续的每天开销划分为至多
思路
二分最大允许开销 limit。从前向后尽量把当天放进当前周期,若会超过 limit 就新开一个周期;这种贪心在给定上限下使用的周期数最少。若周期数不超过
代码
Python代码
python
day_count, month_count = map(int, input().split())
expenses = [int(input()) for _ in range(day_count)]
def can_arrange(limit: int) -> bool:
used_months = 1
current_sum = 0
for expense in expenses:
if current_sum + expense > limit:
used_months += 1
current_sum = expense
else:
current_sum += expense
return used_months <= month_count
low, high = max(expenses), sum(expenses)
while low < high:
middle = (low + high) // 2
if can_arrange(middle):
high = middle
else:
low = middle + 1
print(low)C++代码
cpp
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int n,m;
int a[maxn];
bool check(int val) {
int cnt = 0;
int sum =0;
for(int i =1;i<=n;i++){
if( sum + a[i] > val) {
cnt++;
sum = a[i];
if( sum > val) return false; // 一件物品都装不下
} else {
sum += a[i];
}
}
cnt++;
return cnt <=m;
}
// bs = binary search
int bs_find(int l,int r) {
while(l < r) {
int mid = (l+r) >> 1;
if( check(mid) ) { // 红色
r = mid;
} else { // 蓝色
l = mid+1;
}
}
return l;
}
int main(){
cin >> n >> m;
for(int i =1;i<=n;i++){
cin >> a[i];
}
int pos = bs_find(1,10000 * 100000+1);
cout << pos << endl;
return 0;
}复杂度
时间复杂度为
总结
“最小化最大值”常转化为“给定上限是否可行”的二分判定。