Prev 历届试题 分巧克力
题目如下:
这道题是道简单的贪心题,因为要求切出的巧克力要尽可能大
首先我们要知道怎么在一个长方形的巧克力里切出正方形的巧克力,并且能切出的最大面积的正方形的巧克力取决于什么
1.像例子里说一块6x5的巧克力能切出6块2x2的巧克力,这个算法很简单,就是(6 / 2) x (5 / 2) = 3 x 2 = 6。将长方形的长宽分别除以想切出的正方形的边长,得到的值相乘就是答案
2.那一个长方形能切出来最大的正方形的边长是多少?这个值就是min(长,宽)。比如一个1 x 10的长方形,它只能1 x 1的正方形
知道上面两点,再结合下贪心就能写出代码了。代码和注释如下
import java.util.Scanner;
/**
* @Description: 历届试题 分巧克力
* @ClassName: Prev37
* @author: fan.yang
* @date: 2020/12/23 10:40
*/
public class Prev37 {
//普通法
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int max = 0;
int n = scanner.nextInt();
int k = scanner.nextInt();
int a[][] = new int[n][2];
for(int i = 0;i < n;i++){
a[i][0] = scanner.nextInt();
a[i][1] = scanner.nextInt();
//注意一下这个max 这个max最终代表的是所有巧克力能切的最大正方形的边长
//过程就是 先获取当前巧克力能切的最大正方形边长 min(长,宽)
//然后在从上面获取到的边长中取最大值 贪心所在
max = Math.max(Math.min(a[i][0] , a[i][1]) , max);
}
//根据max 从大到小看
for(int i = max;i >= 1;i--){
int sum = 0;
for(int j = 0;j < n;j++){
//根据公式求出 当前巧克力能切出i x i的正方形多少个
sum += (a[j][0] / i) * (a[j][1] / i);
}
//满足要求 直接退出 因为我是从大到小的 第一次满足就是最大的 符合题目的尽可能大
if(sum >= k){
System.out.println(i);
return;
}
}
}
}
把上面的代码往蓝桥一丢,发现最后一个测试数据接近1s了,这说明算法还是有待优化的。
所以最后加了二分法,最后一组数据能在500ms就跑完了
import java.util.Scanner;
/**
* @Description: 历届试题 分巧克力
* @ClassName: Prev37
* @author: fan.yang
* @date: 2020/12/23 10:40
*/
public class Prev37 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int max = 0;
int n = scanner.nextInt();
int k = scanner.nextInt();
int a[][] = new int[n][2];
for(int i = 0;i < n;i++){
a[i][0] = scanner.nextInt();
a[i][1] = scanner.nextInt();
max = Math.max(Math.min(a[i][0] , a[i][1]) , max);
}
//二分法 注意一下 max要加下1 不然娶不到max的情况
//比如max = 3时,假设3是答案
//第一次 left = 0, right = 3 , mid = 1
//第二次 left = 1, right = 3 , mid = 2
//第三次 left = 2, right = 3 , mid = 2
//这时候循环就结束了 2显然不是最优解 所以max + 1
int left = 0, right = max + 1;
while(left < right - 1){
int mid = (left + right) / 2;
int sum = 0;
for(int j = 0;j < n;j++){
sum += (a[j][0] / mid) * (a[j][1] / mid);
}
if(sum >= k){
left = mid;
}else{
right = mid;
}
}
System.out.println(left);
}
}