Lazy有N个礼物需要打成M个包裹,邮寄给M个人,这些礼物虽然很便宜,但是很重。Lazy希望每个人得到的礼物的编号都是连续的。为了避免支付高昂的超重费,他还希望让包裹的最大重量最小。
输入:一行两个整数N和M。
一行N个整数,表示N个礼物的重量。输出:一个整数,表示最小的最大重量。
样例:
3 2
1 1 2
思路: 本题希望让每个人得到的包裹连续且最大重量最小,那这个最大重量一定在单个最重礼物l和礼物总重量r之间。接下来只需要对这个区间进行二分,每次中值点mid进行判断观察应该是向左半区间进行二分还是右半区间二分,而这个判断条件就是每个包裹重量<=mid,但是包裹数不超过M。
代码:
#include<stdio.h>
int n,m;
int a[1000010];
int l,r,i;
int ans;
int max(int x,int y)
{
if(x>y) return x;
else return y;
}
int check(int mid)
{
int wrap=1;
int sum=a[1];
for(i=2;i<=n;i++)
{
if(sum+a[i]<=mid)//不超过
{
sum+=a[i];
}
else
{
wrap+=1;//包裹数加一
sum=a[i];
}
}
if(wrap<=m) return 1;
else return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);//读入每个包裹重量
l=max(l,a[i]);//l为这几个礼物最重那个,表示左区间
r+=a[i]; //r为这几个礼物总重
}
while(l<=r)//二分
{
int mid=(l+r)/2;
if(check(mid))//检查是否满足条件
{
ans=mid;
r=mid-1;//缩小范围继续二分
}
else l=mid+1;//继续向右半段二分
}
printf("%d",ans);
return 0;
}