导读:
二分查找是一个比较重要且实用的基础算法
题目链接:用户登录
读完题目的大体想法:
题目大致意思就是有几块巧克力分给k个人然后要求在每个人得到巧克力尽可能大的情况下求最大的正方形边长。
第一感觉,如果时间允许,暴力枚举是一定可以出答案的,但是这个题目的数据100000,可能会超时,所以我们就可以自然而然的想到运用二分查找来节约时间去寻找那个最大的边长,这样其实就差不多有感觉了。
处理一下细节:
1.如何得出在当前边长下,能分出几块巧克力:
分出的块数(ans)=(巧克力长度/当前边长)*(巧克力宽度/当前边长);
2.然后ans和人数K比一下,ans>=k说明边长有点小,可以再大一点;ans<k说明边长太大不够分了;
如果处理了以上两个问题其实题目已经出来了,结合二分查找的模板,很容易就写出来了
//find函数就是来判断切出来的巧克力有没有超过有的人数k;
public static boolean find(int mid,int k,int n){
int ans=0;//记录有多少块
for (int i=0;i<n;i++) {
ans += (h[i] / mid) * (w[i] / mid);//遍历累加切出来有多少块巧克力
if (ans >= k) return true;
//这边在循环里直接判断有没有大于k可以稍微节约一点时间,
// 算是小小的优化,写在for循环外面当然也可以;
// 只要当前已经大于k了之后的就不用加了直接返回true
}
return false;
}
public static void main(String[] args) {
int i1=1;//注意二分查找的开头,边长从1开始
int j1=100000;//最大的边长
//常规输入
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int k=sc.nextInt();
for (int i=0;i<n;i++){
h[i]=sc.nextInt();
w[i]=sc.nextInt();
}
while (i1<=j1){ //二分模板就是套!
int mid=(i1+j1)/2;
if (find(mid,k,n)){
i1=mid+1;
}
else {
j1=mid-1;
}
}
System.out.println(j1);
}
在此贴心的附上AC代码:
import java.util.Scanner;
public class Main {
static int [] h=new int [100000];
static int [] w=new int [100000];
public static boolean find(int mid,int k,int n){
int ans=0;
for (int i=0;i<n;i++) {
ans += (h[i] / mid) * (w[i] / mid);
if (ans >= k) return true;
}
return false;
}
public static void main(String[] args) {
int i1=1;
int j1=100000;
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int k=sc.nextInt();
for (int i=0;i<n;i++){
h[i]=sc.nextInt();
w[i]=sc.nextInt();
}
while (i1<=j1){
int mid=(i1+j1)/2;
if (find(mid,k,n)){
i1=mid+1;
}
else {
j1=mid-1;
}
}
System.out.println(j1);
}
}