BZOJ 1052 [HAOI2007]覆盖问题

二分+暴力判断。

这题的思路很巧啊- -,必须去想最小矩形覆盖后的一些性质。

发现用k(1≤k≤3)个正方形,覆盖平面上所有点,要求边与坐标轴平行,那么如果把所有点用一个最小的矩形(边也与坐标轴平行)圈起来,一定有至少一个正方形的一个顶点和矩形的一个顶点重合。证明就是假设没有这种情况,则肯定有矩形的四条边都和三个正方形的某条边重合,因为正方形只有三个,边有四条,不成立,就算是一些特殊情况想一想也可以知道不成立。

于是二分答案就可以判断了,最小矩形构出来,枚举四个点放正方形,然后继续做下去……

#include<cstdio>
#include<algorithm>
#define N 20005
using namespace std;
const int INF = 0x7ffffff;
struct tree{int x, y;}p[N];
int n, ban[N];
void cover(int x, int y, int len, int op)
{
    for(int i = 1; i <= n; i++)
        if(p[i].x>=x&&p[i].y>=y&&p[i].x<=x+len&&p[i].y<=y+len)
            ban[i]+=op;
}
bool dfs(int t, int a)
{
    int l = INF, r = -INF, u = -INF, d = INF;
    for(int i = 1; i <= n; i++)
    {
        if(ban[i]>0)continue;
        l=min(l,p[i].x);
        r=max(r,p[i].x);
        u=max(u,p[i].y);
        d=min(d,p[i].y);
    }
    if(t==3)return (r-l<=a && u-d<=a);
    bool flag=0;
    if(!flag){cover(l,u-a,a,1);flag=dfs(t+1,a);cover(l,u-a,a,-1);}//左上 
    if(!flag){cover(l,d,a,1);flag=dfs(t+1,a);cover(l,d,a,-1);}//左下 
    if(!flag){cover(r-a,u-a,a,1);flag=dfs(t+1,a);cover(r-a,u-a,a,-1);}//右上 
    if(!flag){cover(r-a,d,a,1);flag=dfs(t+1,a);cover(r-a,d,a,-1);}//右下 
    return flag;
}
int main()
{
    scanf("%d",&n);
    for(int i = 1; i <= n; i++)
        scanf("%d%d",&p[i].x,&p[i].y);
    int l = 0, r = INF;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(dfs(1,mid))r=mid;
        else l=mid+1;
    }
    printf("%d\n",l);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值