蓝桥杯:分巧克力

分巧克力【二分搜索】

题目描述

儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。

小明一共有 N 块巧克力,其中第 i 块是 Hi×Wi 的方格组成的长方形。为了公平起见,

小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:

  1. 形状是正方形,边长是整数;
  2. 大小相同;

例如一块 6x5 的巧克力可以切出 6 块 2x2 的巧克力或者 2 块 3x3 的巧克力。

当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?

输入描述

第一行包含两个整数 N,K (1≤N,K≤105)。

以下 N 行每行包含两个整数 Hi,Wi (1≤Hi,*Wi*≤105)。

输入保证每位小朋友至少能获得一块 1x1 的巧克力。

输出描述

输出切出的正方形巧克力最大可能的边长。

输入输出样例

示例

输入

2 10
6 5
5 6

输出

2

思路:

这道题用二分搜索比较简单,可以缩短运行时间,定义两个数组用于储存每个巧克力的长和宽,在定义两个左右指针用于
二分搜索,然后进入二分的循环,要在循环中把cnt这个记录每次能分多少巧克力的变量定义成0,因为每次改变分巧克力的
边长时,对应的每次在mid边长下分的巧克力块数也要重新计算。
最重要的是在最大边长下能分多少块巧克力。我们不能直接推出来边长最大多少,那我们就一个一个的试在一个边长mid
下可以分多少块巧克力cnt,如果分的巧克力数多了,那就把边长加大,因为要求满足要求的最大边长,计算加大边长后是否
还满足要求,如果不满足要求就减小边长,如此重复直到求到满足要求的最大边长。
一块巧克力例如长6 宽5,分成边长为2的巧克力怎样计算? 应该对这块巧克力的长和宽都除2,然后把两个结果相乘,就是
总块数,6/2=3,5/2=2,结果就是3*2=6块,能分成6块。这道题也是这样计算的,用二分找一个边长mid,把所有巧克力按这样的
方法计算的快数相加,看是否满足,不满足减小边长,满足加大边长,直到求出最大边长。

代码:

#include<stdio.h>
int main()
{
	int n,k,count;
	int H[110000],W[110000];  //分别存放巧克力的长和宽 
	scanf("%d %d",&n,&k);
	for(int i=0;i<n;i++)
		scanf("%d %d",&H[i],&W[i]);
	int low=0;  //左指针 
	int hight=100001;  //右指针 
	while(low<=hight)  //进行二分查找 
	{
		int cnt=0; //记录每次巧克力的边长确定时,能分多少块。 
		int mid=(low+hight)/2;  //二分数据 
		for(int i=0;i<n;i++)
			cnt+=(H[i]/mid)*(W[i]/mid); //计算在边长为mid时可以分多少块巧克力 
		if(cnt>=k)  
		{   //如果分的巧克力块数大于总人数
			low=mid+1;  //增大左指针的值使mid增大,重新计算增大后是否依然可以分够 k 块巧克力 
			count=mid;  //记录mid的值,因为可能增大mid后分不出来k块巧克力。 
		}
			
		else 
			hight=mid-1; //如果分的巧克力小于 k 块,则减小右指针使mid增大,重新计算是否能分出k块 
	}
	printf("%d",count);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值