2017年第八届蓝桥杯JAVA A组国赛 —— 第九题:分巧克力(二分查找)

儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形。
为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:
1. 形状是正方形,边长是整数
2. 大小相同
例如一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小Hi计算出最大的边长是多少么?
输入
第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000)
输入保证每位小朋友至少能获得一块1x1的巧克力。
输出
输出切出的正方形巧克力最大可能的边长。
样例输入:
2 10
6 5
5 6
样例输出:
2

import java.util.Scanner;
public class Main {
	//针对每块巧克力都是正方形 所以对一块大巧克力可以 以side为边长 遍历  (length/side)为在长边可以分出来的块数  (width/length)为在宽边可以分出来的块数
	//两种边分出来的块数乘积 就是此巧克力可分的块数  算法解决:每块都至少是个1*1的情况 可以从1开始遍历  遍历到100000 但是算法的时间复杂度过大 可以考虑二分查找
	//二分查找的时间复杂度log2n  
	static int n,k;     // n块巧克力  k个人分 
	static int num;  //巧克力分为k块
	static int[][] chocolate = new int[100005][2];  //巧克力  二维数组上 保存宽和常
	static Scanner sc = new Scanner(System.in);
	public static void main(String[] args) {
		System.out.println("输入x块巧克力,y个人分");
		n = sc.nextInt();
		k = sc.nextInt();
		for(int i = 0; i<n;i++) {
			System.out.println("输入第"+(i+1)+"块的长和宽");
			chocolate[i][0] = sc.nextInt();
			chocolate[i][1] = sc.nextInt();
		}
		System.out.println("最大边长是"+binary(1, 100001));
	}
	
	static int binary(int left,int right) {
		int mid;
		while(left<right) {
			mid = (left+right)/2;
			if(judge(mid)) {
				// 满足人吃 到右侧区间 增大边长 来试探右侧最小范围 
				left = mid+1;
			}else {
				//不满足k个人吃 到左侧区间
				right = mid;
			}
		}
		//当满足 两者相等时 必然是一个不满足条件的 减去1可以找到那个最后满足条件的
		return left-1;
	}
	
	static boolean judge(int side) {
		int temp = 0;
		for(int i = 0;i<n;i++) {
			//遍历 所有的巧克力 确定针对这一边长 此巧克力可以取到的最多数的情况 然后加到一起
			temp = temp + (chocolate[i][0]/side)*(chocolate[i][1]/side);
		}
		//当满足 k个人吃的时候 就是分配合理时候 递归可以往右侧区间  否则到左侧区间(减小边长来换取可以满足人吃)
		if(temp>=k) {
			return true;
		}
		return false;
	}
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值