zoukankan      html  css  js  c++  java
  • 「二分答案 + 搜索」[HAOI2007]覆盖问题

    [HAOI2007]覆盖问题

    题目链接:[HAOI2007]覆盖问题

    题目大意

    给你(n)个坐标,再给你3个(l imes l)的矩阵,让你用这些矩阵去包含这些点,要求是将所有点都包含,我们要求(l)的最小值

    题目题解

    想到二分了,不过没想到怎么爆搜

    看了下题解,妙啊妙啊,牛逼

    每次二分一个 (l) 值作为我们想要的矩阵边长,然后由树的坐标我们可能可以找到比原平面直角坐标系更小的一个坐标系,我们在新的坐标系上进行操作就可以了,但怎么进行操作呢?我们如果想尽可能的缩小新坐标系的大小,我们就得让新坐标系上代表四角坐标的树苗被覆盖,这里就得注意,我们只有3个矩阵,想要尽可能的缩小坐标的大小,就得让前两个矩阵尽可能的落在四角上,然后最后再通过新坐标系的四角,判断最后一个矩阵能否覆盖其所有树苗。

    怎么找?爆搜啊!

    代码如下 (写了半天没写出来,看了下题解发现,woc 我太菜了Orz)

    //#define fre yes
    
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    const int N = 20005;
    struct Tree{
        int x, y;
    } l[N];
    int Vis[N];
    
    int n;
    
    void cover(int lx, int rx, int ly, int ry, int id) {
        for (int i = 1; i <= n; i++) {
            if(!Vis[i] && lx <= l[i].x && rx >= l[i].x && ry >= l[i].y && ly <= l[i].y) {
                Vis[i] = id;
            }
        }
    }
    
    void recover(int id) {
        for (int i = 1; i <= n; i++) {
            if(Vis[i] == id) Vis[i] = 0;
        }
    }
    
    bool dfs(int tot, int k) {
        int lx = 2e9, rx = -2e9, ly = 2e9, ry = -2e9;
        for (int i = 1; i <= n; i++) {
            if(!Vis[i]) {
                lx = std::min(lx, l[i].x);
                rx = std::max(rx, l[i].x);
                ly = std::min(ly, l[i].y);
                ry = std::max(ry, l[i].y);
            }
        }
    
        if(std::max(rx - lx, ry - ly) <= k) return true;
        if(tot == 3) return false;
    
        cover(lx, lx + k, ly, ly + k, tot);
        if(dfs(tot + 1, k)) return true;
        recover(tot);
        cover(lx, lx + k, ry - k, ry, tot);
        if(dfs(tot + 1, k)) return true;
        recover(tot);
        cover(rx - k, rx, ly, ly + k, tot);
        if(dfs(tot + 1, k)) return true;
        recover(tot);
        cover(rx - k, rx, ry - k, ry, tot);
        if(dfs(tot + 1, k)) return true;
        recover(tot);
        return false;
    }
    
    bool check(int prv) {
        memset(Vis, 0, sizeof(Vis));
        return dfs(1, prv);
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d %d", &l[i].x, &l[i].y);
        }
    
        int l = 0, r = 2e9;
        while(l < r) {
            int mid = (l + r) >> 1;
            if(check(mid)) r = mid;
            else l = mid + 1;
        } printf("%d
    ", l);
        return 0;
    }
    
    
  • 相关阅读:
    react ts axios 配置跨域
    npm run eject“Remove untracked files, stash or commit any changes, and try again.”错误
    java 进程的参数和list的线程安全
    帆软报表 大屏列表跑马灯效果JS
    帆软报表 快速复用数据集,避免重复劳动
    分析云 OA中部门分级思路和实现方法
    分析云 分段器 只显示一个块的数据
    分析云 更改服务默认的端口号
    分析云U8项目配置方法新版本(2)
    Oracle 创建时间维度表并更新是否工作日字段
  • 原文地址:https://www.cnblogs.com/Nicoppa/p/11511880.html
Copyright © 2011-2022 走看看