分巧克力【二分搜索】
题目描述
儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
小明一共有 N 块巧克力,其中第 i 块是 Hi×Wi 的方格组成的长方形。为了公平起见,
小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:
- 形状是正方形,边长是整数;
- 大小相同;
例如一块 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;
}