蓝桥每日打卡--分巧克力

#蓝桥#JAVA#分巧克力

问题描述

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

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

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

  1. 形状是正方形,边长是整数;

  2. 大小相同;

例如一块6×5的巧克力可以切出6块2×2的巧克力或者2块3×3的巧克力。

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

思路解析:

采用二分查找(二分法)来确定满足条件的最大正方形边长。二分查找适用于在一个有序的数值范围内查找满足特定条件的数值,这里的有序范围是正方形边长的可能取值范围。

首先,读取两个整数 n 和 k,分别表示巧克力的数量和需要分给的人数。

循环 n 次,每次读取两个整数,分别存储到 h 数组和 w 数组中,代表每块巧克力的高度和宽度。

接着,进入 while 循环,只要 min 小于等于 max,就继续查找:

  • 计算中间值 ave:计算当前查找范围的中间值 ave = (max + min) / 2,作为当前尝试的正方形边长。
  • 计算当前边长下的巧克力块数 cut
    • 初始化 cut 为 0。
    • 遍历每块巧克力,对于每块巧克力,计算其在边长为 ave 时能切出的正方形小块数 (h[i] / ave) * (w[i] / ave),并累加到 cut 中。
  • 根据 cut 的值调整查找范围
    • 如果 cut 小于 k,说明当前边长 ave 太大,切出的巧克力块数不够分给 k 个人,将 max 更新为 ave - 1,缩小查找范围到较小的边长。
    • 如果 cut 大于等于 k,说明当前边长 ave 可以满足要求,将 min 更新为 ave + 1,继续在更大的边长范围内查找,并将 ans 更新为 ave,记录当前符合要求的最大边长。
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int n = scan.nextInt();
        int k = scan.nextInt();
        int[] h=new int[n];
        int[] w=new int[n];
        for (int i = 0; i <n ; i++) {
            h[i] = scan.nextInt();
            w[i] = scan.nextInt();
        }
        //设置所切块数的最大边界max和最小边界min
        int max=100000;
        int min=1;
        int ave;//二分法的中间值
        int cut=0;//所切的块数
        int ans=0;//切出后,每块巧克力最大边长
        //采用二分法,当min>max跳出循环
        //取最大边界和最小边界的平均值(ave)代入循环,while(max>=min)
        while (min<=max){
            ave=(max+min)/2;
            cut=0;
            //循环,多少个n循环多少次,记录所切数目cut
            for (int i = 0; i <n ; i++) {
                cut+=(h[i]/ave)*(w[i]/ave);
            }
            //ave太大不符合要求cut<k,max=ave-1
            if (cut<k)
                max=ave-1;
            //ave小但符合每人都有巧克力的要求cut>k,min=ave+1,记录边长
            else{
                min=ave+1;
                ans=ave;
            }
        }
        System.out.println(ans);
        scan.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值