zoukankan      html  css  js  c++  java
  • bzoj 1052: [HAOI2007]覆盖问题

    Description
    某人在山上种了N棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄
    膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个LL的正方形塑料薄膜将小树遮起来。我们不妨将山建
    立一个平面直角坐标系,设第i棵小树的坐标为(Xi,Yi),3个L
    L的正方形的边要求平行与坐标轴,一个点如果在
    正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求L最小值。
    Input
    第一行有一个正整数N,表示有多少棵树。接下来有N行,第i+1行有2个整数Xi,Yi,表示第i棵树的坐标,保证
    不会有2个树的坐标相同。
    Output
    一行,输出最小的L值。
    Sample Input
    4
    0 1
    0 -1
    1 0
    -1 0
    Sample Output
    1

    解题报告:

    这题明显的二分答案,至于怎么check,需要想一下,朴素的我们会选择从按x轴左到右扫一遍,然后没有被覆盖的就以该点为正方形的左边,选择能覆盖的点最多的去覆盖,这样处理起来复杂度不对且实现很难,那么考虑贪心,每次找出能覆盖所有的点最小矩形,然后搜索四个角,选择一个去覆盖剩余点,然后不断递归,如果最后层数小于3就符合要求.其实思路和这个差不多,因为矩形一定是卡在点上的,相当于以该点为正方形的某个边,然后尽量多的覆盖点

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Max(a,b) ((a)>(b)?(a):(b))
    using namespace std;
    const int N=30005,inf=2e8;
    int x[N],y[N],n;int vis[N];
    void updata(int &xl,int &yl,int &xr,int &yr){
        xl=yl=inf;xr=yr=-inf;
        for(int i=1;i<=n;i++){
            if(vis[i])continue;
            xl=Min(xl,x[i]);yl=Min(yl,y[i]);
            xr=Max(xr,x[i]);yr=Max(yr,y[i]);
        }
    }
    void upd(int xl,int yl,int xr,int yr,int col){
        for(int i=1;i<=n;i++){
            if(!vis[i] && x[i]>=xl && x[i]<=xr && y[i]>=yl && y[i]<=yr)
                vis[i]=col;
        }
    }
    bool dfs(int dep,int mid){
        int X[3],Y[3];
        updata(X[1],Y[1],X[2],Y[2]);
        if(Max(X[2]-X[1],Y[2]-Y[1])<=mid)return true;
        if(dep==3)return false;
        for(int i=1;i<=2;i++){
            for(int j=1;j<=2;j++){
                if(i==1){
                    if(j==1)upd(X[i],Y[j],X[i]+mid,Y[j]+mid,dep);
                    else upd(X[i],Y[j]-mid,X[i]+mid,Y[j],dep);
                }
                else{
                    if(j==1)upd(X[i]-mid,Y[j],X[i],Y[j]+mid,dep);
                    else upd(X[i]-mid,Y[j]-mid,X[i],Y[j],dep);
                }
                if(dfs(dep+1,mid))return true;
                for(int k=1;k<=n;k++)
                    if(vis[k]==dep)vis[k]=false;
            }
        }
        return false;
    }
    bool check(int mid){
        memset(vis,0,sizeof(vis));
        return dfs(1,mid);
    }
    void work()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&x[i],&y[i]);
        }
        int l=1,r=2e9,mid,ans=-1;
        while(l<=r){
            mid=(l+r)>>1;
            if(check(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d
    ",ans);
    }
    
    int main()
    {
        work();
        return 0;
    }
    
  • 相关阅读:
    js模拟点击加载事件代码
    js添加节点
    js数字随机产生并相加
    转:Selenium借助AutoIt识别上传(下载)详解
    [原创] web_custom_request 与 Viewstate
    转:浏览器与WEB服务器工作过程举例
    转:WebDriver(Selenium2) 处理可能存在的JS弹出框
    转:Loadrunner报错“Too many local variablesAction.c”解决方法
    转:loadrunner关联及web_reg_save_param方法浅析
    转:性能测试流程剖析
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7435323.html
Copyright © 2011-2022 走看看