矩形分割(二分)

描述

平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R)。大矩形内部包含一些小矩形,小矩形都平行于坐标轴且互不重叠。所有矩形的顶点都是整点。要求画一根平行于y轴的直线x=k(k是整数) ,使得这些小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小。并且,要使得大矩形在直线左边的的面积尽可能大。注意:若直线穿过一个小矩形,将会把它切成两个部分,分属左右两侧。

输入

第一行是整数R,表示大矩形的右上角坐标是(R,R) (1 <= R <= 1,000,000)。
接下来的一行是整数N,表示一共有N个小矩形(0 < N <= 10000)。
再接下来有N 行。每行有4个整数,L,T, W 和 H, 表示有一个小矩形的左上角坐标是(L,T),宽度是W,高度是H (0<=L,T <= R, 0 < W,H <= R). 小矩形不会有位于大矩形之外的部分。

输出

输出整数n,表示答案应该是直线 x=n。 如果必要的话,x=R也可以是答案。

样例输入

1000
2
1 1 2 1
5 1 2 1

样例输出

5

提示:

1 预处理一下,开两个数组记录某线左右各有多少。记得用long long
2 小矩形只有一个而且宽为1时,答案是R而不是小矩形的右边x坐标  
3 二分及预处理  
4 用mid模拟答案,合符输出,不合符根据条件选取左右区间再次二分
#include<iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define p 10001
using namespace std;
struct node{
    int l;
    int t;
    int w;
    int h;
}nodes[p];
int r,n;
long long cha;
int mid,lleft,rright;
long long check(int mid){//返回左右小矩形面积之差
    long long larea=0;
    long long rarea=0;
    for(int i=0;i<n;i++){
        if(nodes[i].l>=mid){
            rarea+=nodes[i].w*nodes[i].h;
        }
        else{
            if(nodes[i].l+nodes[i].w>mid){    //分割线位于矩形中间时
                rarea+=(nodes[i].l+nodes[i].w-mid)*nodes[i].h;
                larea+=(mid-nodes[i].l)*nodes[i].h;
            }
            else{
                larea+=nodes[i].w*nodes[i].h;
            }
        }
    }
    cha=larea-rarea;
    return cha;
}
int zhixian(){
    lleft=0;
    rright=r;
     while(lleft<=rright)
        {
        mid=(lleft+rright)/2;
        if(check(mid)<0)
            lleft=mid+1;
        else if(check(mid)>0)//此时左边小矩形总面积大于右边的了,为使左右面积之差最小,分割线再往右移
           rright=mid-1;
        else
            return mid;
    }

    return lleft;
}
int main(){
    scanf("%d",&r);
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d%d%d",&nodes[i].l,&nodes[i].t,&nodes[i].w,&nodes[i].h);
    }
    if(n==1&&nodes[n-1].w==1){//当只有一个矩形且宽为1时,因不能在其中间进行分割,故分割线直接为大矩形的右端坐标
        printf("%d\n",r);
        return 0;
    }
    int aa=zhixian();
    while(check(aa)==check(aa+1)&&aa<r)//此时已找到使两边面积之差最小的分割线,为了使左侧大矩形面积最大,若分割线往右移,恰好处于空白区域,即左右两边小矩形面积之差不变
        aa++;
     printf("%d\n",aa);

}

猜你喜欢

转载自blog.csdn.net/lijunyan5/article/details/81539642