问题描述
Lazy有N个礼物需要打成M个包裹,邮寄给M个人,这些礼物虽然很便宜,但是很重。Lazy希望每个人得到的礼物的编号都是连续的。为了避免支付高昂的超重费,他还希望让包裹的最大重量最小。
输入格式
一行两个整数N和M。
一行N个整数,表示N个礼物的重量。
输出格式
一个整数,表示最小的最大重量。
样例输入
3 2 1 1 2
样例输出
2
数据规模和约定
N, M <= 100,000
重量 <= 1,000
结合csdn上Java和Python的题解,写出C++的题解
代码如下
#include<iostream>
using namespace std;
int weight[100010];
int b[100010];
int num,package;
bool judge(int mid){
int curPack=1;//打包的数量
int sum=0; //前几个包打包的重量
for(int i=0;i<num;i++){
sum+=weight[i];//前几个包打包的重量
if(curPack>package){//已打包数量比送出的多 ,不合理
return false;
}
if(sum>mid){//打包的重量大于当前最大重量
sum=0;//对包的重量归零,对下一个的重量进行计算
curPack+=1;//放到下一个包打包
i-=1;//对最后一个来打包的包不打包
}
else if(sum==mid){//相等就不用把最后一个来打包的包拿出来了
sum=0;
curPack+=1;
}
}
return true;
}
int main() {
cin>>num>>package;
int right=0;
for(int i=0;i<num;i++){
cin>>weight[i];//输入未打包的各个包的重量
right+=weight[i];//二分最右端是总重量
}
int mid=0;//中间值
int left=0;//最左值
while(left<right){
mid=(left+right)/2;
if(judge(mid)){//判断是否能够打包
right=mid;//在左半边找
}
else{
left=mid+1;//在右半边找
}
}
cout<<left;//左边的值是最小的最大打包重量
return 0;
}
使用二分法查找符合条件的值,在判断条件里枚举。
最小的最大包的重量存在于包的最大重量和包的总重量中,因此使用二分法。
使用枚举,进行打包,再看最终打包的数量是否大于分给朋友的数量,如果大于那么这个值不合适,寻找下一个最小的最大包重量进行判断。