分巧克力
题目描述
核心思路
设被分割成的正方形的个数为res,正方形的边长为a,那么有 r e s = W a ∗ H a = W H a 2 res=\dfrac {W}{a}*\dfrac {H}{a}=\dfrac {WH}{a^2} res=aW∗aH=a2WH。由这个式子可以发现,当边长a增大时,个数res减小;当边长a减小时,个数res增大。也就是说,边长a具有单调性。注意这里说的边长a具有单调性,是说我们分割出来的正方形的边长具有单调性,而不是说题目输入的那个长、宽具有单调性。既然我们切割出来的边长a具有单调性,具有单调性一定可以用二分!!!
所以这道题可以用二分来求解,假设某个边长 x x x是使得刚好能分给K个小朋友,由公式可知,对于所有 ≤ x \leq x ≤x的边长都一定是 ≥ K \geq K ≥K的,那么就是满足题意的,对于所有 > x >x >x的边长都一定是 < K <K <K的,那么就不符合题意。
重新整理一下题意就是:找到 ≤ x \leq x ≤x的所有边长中的最大的那个边长,即最小值的最大,那么就可以用二分模板了。考虑二分的范围:题目说至少可以分得一块 1 × 1 1\times 1 1×1的巧克力,也就是说分割出来的正方形的最小是1。而我们的二分算法就是找边长,因此二分的左范围是1。题目给的长、宽的最大范围是1e5。从实际意义出发,假设我们二分出来的边长大于了输入的最大1e5,那么怎么可能从1e5中分割出比1e5还大的数呢?因此,二分的右范围是1e5。
问题:如何理解 W a ∗ H a \dfrac {W}{a}*\dfrac {H}{a} aW∗aH就是被分割成的正方形的个数呢?
问题:如何理解二分模板呢?
代码
#include<iostream>
using namespace std;
typedef long long LL;
const int N=1e5+10;
//巧克力的长 宽
int h[N],w[N];
int n,k;
//check一下某个边长mid是否能够满足题意
bool check(int mid)
{
LL res=0; //切割出的正方形的个数
for(int i=0;i<n;i++)
{
res+=(LL)(h[i]/mid)*(w[i]/mid);
//能够分给k个小朋友,则满足题意
if(res>=k)
return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%d%d",&h[i],&w[i]);
//二分的左范围、右范围
int l=1,r=1e5;
while(l<r)
{
int mid=l+r+1>>1;
if(check(mid))
l=mid;
else
r=mid-1;
}
printf("%d\n",r);
return 0;
}