蓝桥杯真题 分巧克力 题解

题目:
问题描述
  儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
  小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形。
  为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:
  1. 形状是正方形,边长是整数
  2. 大小相同
  例如一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。
  当然小朋友们都希望得到的巧克力尽可能大,你能帮小Hi计算出最大的边长是多少么?
输入格式
  第一行包含两个整数N和K。(1 <= N, K <= 100000)
  以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000)
  输入保证每位小朋友至少能获得一块1x1的巧克力。
输出格式
  输出切出的正方形巧克力最大可能的边长。
样例输入
2 10
6 5
5 6
样例输出
2
数据规模和约定
  峰值内存消耗(含虚拟机) < 256M
  CPU消耗 < 1000ms

思路:
枚举巧克力被分割的边长,如果用for循环从1到(10)^5,则复杂度(10)^10>(10)^8,明显超时..改用二分查找
在判断边长为len时能否满足条件时:求一块长方形(h * w)最多被分成的正方形(len * len)巧克力个数为:
cnt = (h / len) * (w / len)

Code:

#include 
#include 
#include 
using namespace std;
const int maxn = 100010;
const int maxl = 100010;
struct Cho{
    int w,h;
}cho[maxn];
int n,k;

//判断能否将巧克力分成边长为len的正方形k份以上
//能返回true,否则返回false 
bool part(int len){
    int cnt = 0;
    for(int i = 0; i < n; ++i){
        cnt += (cho[i].h / len) * (cho[i].w / len);
    }
    if(cnt >= k) return true;
    return false;
}

//寻找从[1,maxl]中能满足分巧克力条件的最大的边长
//寻找有序序列中最后一个 满足条件的位置
//寻找有序序列中第一个不能满足条件的位置-1 
int solve(int left, int right){
    int mid;
    while(left < right){
        mid = left + (right - left) / 2;
        if(!part(mid)){
            right = mid;
        }
        else{
            left = mid + 1;
        }
    }
    return left - 1;
} 

int main(){
//  fstream cin("a.txt");
    cin>>n>>k;
    for(int i = 0; i < n; ++i){
        cin >> cho[i].w >> cho[i].h;
    }
    cout<1, maxl)<return 0;
}

你可能感兴趣的:(算法,蓝桥杯)