• [HAOI2007] 覆盖问题


    给定平面上若干点,用三个等大的正方形去覆盖(在边界上也算被覆盖),边平行于坐标轴,求最小边长。(n leq 20000)

    Solution

    为什么是三个矩形?

    • 对于 (k) 个矩形的覆盖方案,至少各有一个矩形与四条边界重合

    而当 (kleq3) 时,如果每个矩形都恰好只沾了一条边界,那么与上述引理矛盾,因此

    • 对于 (k leq 3) 个矩形的覆盖方案,至少有一个矩形与边界矩形的一个角重合

    因此,考虑二分,检验答案时,我们只需要枚举下一个矩形放在哪个角上,然后算出去掉这些点后的边界,并递归做下去即可

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    
    const int N = 20005;
    int n,x[N],y[N],u[N],a;
    
    int dfs(int k) {
        int xl=1e9,xr=-1e9,yl=1e9,yr=-1e9;
        for(int i=1;i<=n;i++) if(u[i]==0) {
            xl=min(xl,x[i]);
            yl=min(yl,y[i]);
            xr=max(xr,x[i]);
            yr=max(yr,y[i]);
        }
        if(k==1) {
            if(xr-xl<=a && yr-yl<=a) return 1;
            return 0;
        }
        else {
            int tmp=0;
            vector <int> v;
            for(int i=1;i<=n;i++) {
                if(xl<=x[i] && x[i]<=xl+a && yl<=y[i] && y[i]<=yl+a && u[i]==0) {
                    v.push_back(i);
                    u[i]=1;
                }
            }
            tmp = dfs(k-1);
            for(int i=0;i<v.size();i++) u[v[i]]=0;
            v.clear();
            if(tmp) return 1;
            for(int i=1;i<=n;i++) {
                if(xl<=x[i] && x[i]<=xl+a && yr-a<=y[i] && y[i]<=yr && u[i]==0) {
                    v.push_back(i);
                    u[i]=1;
                }
            }
            tmp = dfs(k-1);
            for(int i=0;i<v.size();i++) u[v[i]]=0;
            v.clear();
            if(tmp) return 1;
            for(int i=1;i<=n;i++) {
                if(xr-a<=x[i] && x[i]<=xr && yl<=y[i] && y[i]<=yl+a && u[i]==0) {
                    v.push_back(i);
                    u[i]=1;
                }
            }
            tmp = dfs(k-1);
            for(int i=0;i<v.size();i++) u[v[i]]=0;
            v.clear();
            if(tmp) return 1;
            for(int i=1;i<=n;i++) {
                if(xr-a<=x[i] && x[i]<=xr && yr-a<=y[i] && y[i]<=yr && u[i]==0) {
                    v.push_back(i);
                    u[i]=1;
                }
            }
            tmp = dfs(k-1);
            for(int i=0;i<v.size();i++) u[v[i]]=0;
            v.clear();
            if(tmp) return 1;
        }
        return 0;
    }
    
    int check() {
        for(int i=1;i<=n;i++) u[i]=0;
        int tmp=dfs(3);
        return tmp;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n;
        for(int i=1;i<=n;i++) cin>>x[i]>>y[i];
        int l=0,r=2e9;
        while(l<r) {
            a=(l+r)/2;
            if(check()) r=a;
            else l=a+1;
        }
        cout<<l;
    }
    
    
  • 相关阅读:
    {Notes}{Latex}{multirow}
    [Reship] Mean Shift 算法介绍
    {Notes}{LaTeX}{enumerate}
    This is a test.
    js中的执行环境和作用域链
    js的预解析
    js笔试题一套(未完待续)
    使用setTimeout 来实现setInterval的效果
    ie6 ie7下报脚本错误"Expected identifier, string or number" 的原因和解决方法
    【雕爷学编程】Arduino动手做(63)---TCS3200D颜色识别传感器
  • 原文地址:https://www.cnblogs.com/mollnn/p/12381768.html
Copyright © 2020-2023  润新知