ADV-1175 打包(二分)
问题描述
Lazy有N个礼物需要打成M个包裹,邮寄给M个人,这些礼物虽然很便宜,但是很重。Lazy希望每个人得到的礼物的编号都是连续的。为了避免支付高昂的超重费,他还希望让包裹的最大重量最小。
输入格式
一行两个整数N和M。
一行N个整数,表示N个礼物的重量。
输出格式
一个整数,表示最小的最大重量。
数据规模和约定
N, M <= 100,000
重量 <= 1,000
思路
最大值最小,先看看能不能二分
二分包裹的重量,二分的区间是[所有重量的最大值,所有重量之和]
,设答案为x,大于x的重量一定能打包成M份,重量小于x的不能打包成M份,具有二段性
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int w[N];
int n, m;
bool check(int x)
{
int val = 0, cnt = 1;
for(int i = 1; i <= n; i ++ )
{
val += w[i];
if(val > x) // 超过当前包裹的最大重量了,就新增一个包裹
{
cnt ++;
val = w[i];
}
if(cnt > m) return false; // 包裹的数量大于需要打包的数量
}
return true;
}
int main()
{
cin >> n >> m;
int maxv = -1, sum = 0;
for(int i = 1; i <= n; i ++ )
{
scanf("%d", &w[i]);
maxv = max(maxv, w[i]);
sum += w[i];
}
int l = maxv, r = sum; // 二分的区间
while(l < r)
{
int mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << l;
return 0;
}