【蓝桥杯】算法提高 打包

问题描述

Lazy有N个礼物需要打成M个包裹,邮寄给M个人,这些礼物虽然很便宜,但是很重。Lazy希望每个人得到的礼物的编号都是连续的。为了避免支付高昂的超重费,他还希望让包裹的最大重量最小。

输入格式

一行两个整数N和M。
  一行N个整数,表示N个礼物的重量。

输出格式

一个整数,表示最小的最大重量。

样例输入

3 2
1 1 2

1、解题思路

​ 共有N个礼物,需要进行M次打包,希望让每个人得到的包裹连续且最大重量最小,假设所有礼物的总重量为sum ,所有礼物中最重的礼物为max ,那么答案只有能可能出现[max,sum] 这个区间内部,我们可以给定一个属于区间[max,sum]的一个重量 t a r g e t target target为每个包裹可以装入的最大重量。

​ 那么我们如何判断 t a r g e t target target最大重量下能够进行M次打包呢?因为打包的礼物必须是连续的,因此从第一个礼物开始遍历,看看最大重量 t a r g e t target target下 N 个礼物需要打多少个包,如果小于等于M,说明每个包最大重量为 t a r g e t target target是能够装下,符合题意。题目要求尽量获得最小的重量,这里使用二分的方法,左区间:max,右区间:sum,封装函数 j u d g e judge judge判断能够打包 ,取区间中间值mid,如果judge判断为true,说明mid下能满足题意,right=mid,否则left=mid+1,直到遍历出结果

2、代码
import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        int num = cin.nextInt();
        int pack = cin.nextInt();
        int []weight=new int[num];
        int right=0,left=0;
        for(int i=0;i<num;++i){
            weight[i]=cin.nextInt();
            right+=weight[i];
        }
        int mid=0;
        //二分查找
        while(left<right){
            mid=(left+right)/2;
            if(judge(weight,mid,pack)){
                right = mid;
            }
            else{
                left=mid+1;
            }
        }
        System.out.println(left);
    }
    private static boolean judge(int[] weight, int mid,int pack) {
        //curWeight 保存当前这个包的重量
        int curWeight=0;
       	//curPack 保存的需要打包数量
        int curPack=1;
        for(int val:weight){
            // 如果超出了所给定的最大打包数量,返回false
            if(val>mid) {
                return false;
            }
            curWeight+=val;
            // 超过了单个包的最大重量,打一个新的包
            if(curWeight>mid){
                curWeight=val;
                curPack+=1;
            }
        }
        return curPack<=pack;
    }
}
  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋刀鱼与猫_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值