zoukankan      html  css  js  c++  java
  • 分巧克力

    分巧克力

    题目描述

    儿童节那天有 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;
    }
    
    追求吾之所爱
  • 相关阅读:
    money 和 smallmoney
    Sql server decimal 和 numeric
    SQL server数据类型int、bigint、smallint、tinyint
    c# 的传递参数值传递与传递引用的区别,ref与out区别
    释放SQL Server占用的内存
    JavaScript学习总结(一)——JavaScript基础
    js1
    Expected URL scheme 'http' or 'https' but no colon was found
    转载:SpringBoot Process finished with exit code 0
    转载:十大经典排序算法(动图演示)
  • 原文地址:https://www.cnblogs.com/rstz/p/14390961.html
Copyright © 2011-2022 走看看