分巧克力

分巧克力

题目描述

儿童节那天有 K 位小朋友到小明家做客。

小明拿出了珍藏的巧克力招待小朋友们。

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

为了公平起见,小明需要从这 N 块巧克力中切出 K 块巧克力分给小朋友们。

切出的巧克力需要满足:

  1. 形状是正方形,边长是整数
  2. 大小相同

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

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

输入格式

第一行包含两个整数 NN 和 KK。

以下 NN 行每行包含两个整数 HiHi 和 WiWi。

输入保证每位小朋友至少能获得一块 1×11×1 的巧克力。

输出格式

输出切出的正方形巧克力最大可能的边长。

数据范围

1≤N,K≤105
1≤Hi,Wi≤105

输入样例:

2 10
6 5
5 6

输出样例:

2

思路分析

此题,无非是把一位的问题扩展到所谓的二维问题,其实题目中条件说,必须分出来的巧克力,是正方型,也就表明我们可以枚举边的长度,在计算出一块巧克力能分出多少块这样的正方型。

重点: 如何计算长方形巧克力,能分出多少块这样边长的巧克力?

  • 推理可知,必须当 正方形的边长小于 长方形中边最小的一边才能成功分出对应大小的正方形巧克力,也就是满足条件 w < = m i n ( H , W ) w<=min(H,W) w<=min(H,W).
  • 所以我们可以通过公式: ( H [ i ] / w ) ∗ ( W [ i ] ) / w (H[i]/w) * (W[i])/w (H[i]/w)(W[i])/w 计算出第 i 块巧克力能分成边长是 w 的巧克力数量。

注意:中间数m所属于的区间范围,来选择二分模板。

解题代码

Java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int k = cin.nextInt();

        int[] H = new int[n];
        int[] W = new int[n];

        for (int i = 0; i < n; ++ i) {
            H[i] = cin.nextInt();
            W[i] = cin.nextInt();
        }
        int ans = breash(H, W, k);
        System.out.println(ans);

    }
    public static boolean check(int m, int[] H, int[] W, int k) {
        int sum = 0;
        for (int i = 0; i < H.length; ++ i) {
            sum += (H[i]/m) * (W[i]/m); // 计算第i块巧克力能分成几块m边长的正方形

            if (sum >= k) return true;
        }
        return false;
    }

    public static int breash(int[] H, int[] W, int k) {
        int l = 1;
        int r = 100000;
        while (l < r) {
            int m = (l + r + 1) >> 1;
            if (check(m, H, W, k)) l = m;
            else r = m - 1;
        }
        return r;
    }

}

C++

#include <iostream>
using namespace std;

const int N = 1e5 + 5;
int h[N], w[N];
int n, k;

bool check(int m) {
    int sum = 0;
    for (int i = 0; i < n; ++ i) {
        sum += (h[i]/m)*(w[i]/m);
        if (sum >= k) return true;
    }
    return false;
}

int breash() {
    int l = 1;
    int r = 1e5;
    while (l < r) {
        int m = (l + r + 1) >> 1;
        if (check(m)) l = m;
        else r = m - 1;
    }
    return l;
}

int main() {
    cin >> n >> k;
    for (int i = 0; i < n; ++ i) {
        cin >> h[i] >> w[i];
    }
    
    int ans = breash();
    cout << ans << endl;
    return 0;
}
posted @ 2021-01-22 22:48  ACWink  阅读(90)  评论(0编辑  收藏  举报