蓝桥杯 分巧克力

OJ链接: 历届试题 分巧克力

问题描述

  儿童节那天有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


本题属于二分。

  • 代码:
#include <bits/stdc++.h>

#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 100010
#define MAX 0x06FFFFFF
#define V vector<int>
#define ll long long 

using namespace std;

typedef struct Node{
    int w,h;
}Node; 

Node ck[LEN];
int N,K;

int calc(int x){
    int i;
    int ans=0;
    FF(i,N){
        ans+=(ck[i].h/x)*(ck[i].w/x); 
    }
    return ans;
}

int main(){
    freopen("input8.txt","r",stdin);  
    I("%d%d",&N,&K);
    int i,h,w;
    FF(i,N){
        I("%d%d",&ck[i].h,&ck[i].w);
    }
    int l=1,r=100000+1,mid;
    while(l<r){
        mid=(l+r)/2;
        int cks=calc(mid);
        if(cks>=K){ //范围右移 
            l=mid+1; 
        }else{
            r=mid;
        }
    }
    O("%d\n",l-1);
    return 0;  
}

  • 分析

这里给出的代码应该属于二分中的upper_bound类型,即找到第一个大于指定元素的索引:

    int l=0;    //初始化 l ,为第一个合法地址
    int r=10;    //初始化 r , 地址的结束地址
    int mid;
    while(l<r) {
        mid=(l+r)/2;
        if(arr[mid]>obj){    //范围左移
            r=mid;
        }else{    //范围右移
            l=mid+1;
        }
    }

改写本题代码为上文标准形式,也可以AC:

    while(l<r){
        mid=(l+r)/2;
        int cks=calc(mid);
        if(cks<K){  //范围左移 
            r=mid;
        }else{      //范围右移 
            l=mid+1; 
        }
    }

猜你喜欢

转载自blog.csdn.net/tqcai666/article/details/80401919