BZOJ 1052: [HAOI2007]覆盖问题

BZOJ 1052: [HAOI2007]覆盖问题

题意:给定平面上横纵坐标在-1e9~1e9内的20000个整数点的坐标,用三个大小相同边平行于坐标轴的正方形覆盖(在边界上的也算),问正方形的边长最小为多少?(整数)

思路:构造一个覆盖所有点的矩形正方形的端点即为矩形的一角,这样枚举四个角的两个正方形,二分最大长度,看剩下的点是否能被第三个正方形覆盖。
ps:构造矩形的思想是看了题解才想到的。。。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define rep(i,n) for((i) = 0;i < n;i++)
struct Point{
    int x[20200], y[20200],top;
}a;
const int inf = 1000000000;
void cut(Point &a,int x1,int y1,int x2,int y2)
{
    Point b;
    b.top = a.top;
    for(int k = 1;k <= a.top;k++)
        b.x[k] = a.x[k],b.y[k] = a.y[k];
    a.top = 0;
    for(int i = 1;i <= b.top;i++)
        if(b.x[i] < x1 || b.x[i] > x2 || b.y[i] < y1 || b.y[i] > y2){
            a.x[++a.top] = b.x[i];
            a.y[a.top] = b.y[i];
        }
}
void solve(Point &a,int id,int mid)
{
    int x1 = inf ,x2 = -inf ,y1 = inf ,y2 = -inf;
    for(int k = 1;k <= a.top;k++){
        x1 = min(x1,a.x[k]);x2 = max(x2,a.x[k]);
        y1 = min(y1,a.y[k]);y2 = max(y2,a.y[k]);
    }
    if(id == 1)
        cut(a,x1,y1,x1+mid,y1+mid);
    if(id == 2)
        cut(a,x1,y2-mid,x1+mid,y2);
    if(id == 3)
        cut(a,x2-mid,y1,x2,y1+mid);
    if(id == 4)
        cut(a,x2-mid,y2-mid,x2,y2);
}
bool judge(int mid)
{
    Point b;
    for(int i = 1;i <= 4;i++){
        for(int j = 1;j <= 4;j++){
            b.top = a.top;
            for(int k = 1;k <= b.top;k++)
                b.x[k] = a.x[k],b.y[k] = a.y[k];
            solve(b,i,mid);
            solve(b,j,mid);    //可以只是一个正方形;
            int x1 = inf ,x2 = -inf ,y1 = inf ,y2 = -inf;
            for(int k = 1;k <= b.top;k++){
                x1 = min(x1,b.x[k]);x2 = max(x2,b.x[k]);
                y1 = min(y1,b.y[k]);y2 = max(y2,b.y[k]);
            }
            if(x2 - x1 <= mid && y2 - y1 <= mid) return true;
        }
    }
    return false;
}
int main()
{
    int n,xx,yy;
    cin>>n;
    a.top = n;
    for(int i = 1;i <= n;i++){
        scanf("%d%d",&xx,&yy);
        a.x[i] = xx;
        a.y[i] = yy;
    }
    int l = 0,r = inf,ans;
    while(l <= r){
        int mid = (l + r) >> 1;
        if(judge(mid))
            ans = mid,r = mid - 1;
        else l = mid + 1;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2016-01-27 13:52  hxer  阅读(175)  评论(0编辑  收藏  举报