蓝桥杯—打包

1、问题描述

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

输入格式

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

输出格式

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

样例输入

3 2
1 1 2

样例输出

2

2、思路分析

一句话说明问题:使包裹的最大重量最小

例子1:

        当有3个礼物,3个包裹时,每个礼物的重量为1,2,3。

        最大重量的最小值就是3。

例子2:

        当有3个礼物,1个包裹时,每个礼物的重量为1,2,3。

        最大重量的最小值就是6。

例子3:

        当有4个礼物,2个包裹时,每个礼物的重量为1,2,3,4。

        最大重量的最小值就是6。      前三个礼物为一个包裹,最后一个礼物为一个包裹

通过观察可以发现:包裹重量的最小值是礼物的最大值,包裹重量的最大值是全部礼物的和。确定了左边界和右边界,使用二分查找即可。

3、代码实现

import java.util.Scanner;

public class 打包 {
	static int n;
	static int pack;
	static int[] weight; 
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		pack = scanner.nextInt();
		//左边界为最重的礼物
		int left = 0;
		//右边界为所有礼物的和
		int right = 0;
		weight = new int[n];
		for(int i = 0;i < n;i++) {
			weight[i] = scanner.nextInt();
			left = Math.max(left, weight[i]);
			right += weight[i];
		}
		//二叉查找
		int mid = 0;
		while(left < right) {
			mid = (left + right) >> 1;
			if(check(mid)) {
				//程序执行到这里,说明mid重量是可行的,我们还要尽可能的找到最小的重量
				right = mid;
			}else {
				//程序执行到这里,说明mid重量是不可行的,mid太小了。不足以将全部礼物打包。
				left = mid + 1;
			}
		}
		System.out.println(left);
	}
	public static boolean check(int target) {
		//当前包裹的重量
		int curWeight = 0;
		//占用了几个包裹
		int curPack = 1;
		//遍历全部礼物
		for(int value : weight) {
			curWeight += value;
			//当前包裹的重量满了后,需要再次添加包裹
			if(curWeight > target) {
				curWeight = value;
				curPack++;
			}
		}
		//当前使用的包裹小于指定的包裹是可行的。
		return curPack <= pack;
	}
}

 

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@小红花

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

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

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

打赏作者

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

抵扣说明:

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

余额充值