zoukankan      html  css  js  c++  java
  • HDU 5046 Airport【DLX重复覆盖】

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5046

    题意:

    给定n个城市的坐标,要在城市中建k个飞机场,使城市距离最近的飞机场的最长距离最小,求这个最小距离。

    分析:

    最小化最大值,显然二分最大距离。然后我们将距离在范围内的两个城市建边,看能否选出k个城市,使得覆盖了所有城市。
    将点之间的关系转化成01矩阵的覆盖问题,重复覆盖,建好边套个DLX即可。
    看了鸟神博客,这里可以直接将所有距离保存在一个数组中,排序并去重,二分下标即可。这样快了很多很多!
    hdu 2295 和这题一个套路,更裸一些。
    跳舞链好强大,可惜只会用模板,这个讲的还挺清晰

    代码:

    /*************************************************************************
        > File Name: O.cpp
        > Author: jiangyuzhu
        > Mail: 834138558@qq.com
        > Created Time: Fri 08 Jul 2016 03:31:58 PM CST
     ************************************************************************/
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<map>
    using namespace std;
    #define sal(n) scanf("%I64d", &(n))
    #define sa(n) scanf("%d", &(n))
    typedef long long ll;
    const int maxn = 3600 + 5, maxc = 60 + 5, maxr = 60 + 5, inf = 0x3f3f3f3f;
    struct Node{ll x; ll y;}city[maxn];
    int L[maxn], R[maxn], D[maxn], U[maxn], C[maxn];
    int S[maxc], H[maxr], size;
    int n, m, k;
    ll d[maxr][maxc], t[maxn];
    ///不需要S域
    void Link(int r, int c)
    {
        S[c]++; C[size] = c;
        U[size] = U[c]; D[U[c]] = size;
        D[size] = c; U[c] = size;
        U[c] = size;
        if(H[r] == -1) H[r] = L[size] = R[size] = size;
        else {
            L[size] = L[H[r]]; R[L[H[r]]] = size;
            R[size] = H[r]; L[H[r]] = size;
        }
        size++;
    }
    void remove(int c)
    {
        for(int i = D[c]; i != c; i = D[i])
            L[R[i]] = L[i], R[L[i]] = R[i];
    }
    void resume(int c)
    {
        for (int i = U[c]; i != c; i = U[i])
            L[R[i]] = R[L[i]] = i;
    }
    int h()
    {///用精确覆盖去估算剪枝
        int ret = 0;
        bool vis[maxc];
        memset (vis, false, sizeof(vis));
        for(int i = R[0]; i; i = R[i]){
            if(vis[i]) continue;
            ret++;
            vis[i] = true;
            for (int j = D[i]; j != i; j = D[j])
                for (int k = R[j]; k != j; k = R[k])
                    vis[C[k]] = true;
        }
        return ret;
    }
    int ans;
    bool Dance(int a) //具体问题具体分析
    {               
        if(a + h() > k) return 0;
        if(!R[0]) return a <=  k;
        int c = R[0];
        for (int i = R[0]; i; i = R[i])
            if(S[i] < S[c]) c = i;
        for(int i = D[c]; i != c; i = D[i]){
            remove(i);
            for(int j = R[i]; j != i; j = R[j])
                remove(j);
            if(Dance(a + 1)) return 1;
            for (int j = L[i]; j != i; j = L[j])
                resume(j);
            resume(i);
        }
        return 0;
    }
    void initL(int x)///col is 1~x,row start from 1
    {
        for (int i = 0; i <= x; ++i){
            S[i] = 0;
            D[i] = U[i] = i;
            L[i+1] = i; R[i] = i+1;
        }///对列表头初始化
        R[x] = 0;
        size = x + 1;///真正的元素从m+1开始
        memset (H, -1, sizeof(H));
        ///mark每个位置的名字
    }
    ll dist(int i, int j)
    {
        ll d = abs(city[i].x - city[j].x) +  abs(city[i].y - city[j].y);
        return d;
    }
    bool judge(ll mid)
    {
        initL(n);
        ans = 0x3f3f3f3f;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                if(d[i][j] <= mid){
                    Link(i, j);
                }
            }
        }
        return Dance(0);
    }
    int main (void)
    {
        int T;sa(T);
        for(int tt = 1; tt <= T; tt++){
            sa(n);sa(k);
            ll maxd = 0;
            int cnt = 0;
            for(int i = 1; i <= n; i++){
                scanf("%I64d%I64d", &city[i].x, &city[i].y);
            }
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= n; j++){
                    d[i][j] = dist(i, j);
                    t[cnt++] = d[i][j];
                }
            }
            sort(t, t + cnt);
            int ncnt = unique(t, t + cnt) - t;
            ll l = -1, r = ncnt;
            while(r - l > 1){
                ll mid = (l + r) / 2;
                if(judge(t[mid])) r = mid;
                else l = mid;
            }
            printf("Case #%d: %I64d
    ", tt, t[r]);
        }
        return 0;
    }
    
    
    
    
  • 相关阅读:
    Network (poj1144)
    C. Hongcow Builds A Nation
    ZYB loves Xor I(hud5269)
    D. Chloe and pleasant prizes
    Game(hdu5218)
    约瑟夫环的递推方法
    Misaki's Kiss again(hdu5175)
    Exploration(hdu5222)
    B. Arpa's weak amphitheater and Mehrdad's valuable Hoses
    C. Arpa's loud Owf and Mehrdad's evil plan
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758613.html
Copyright © 2011-2022 走看看