(中等) HDU 5046 Airport ,DLX+可重复覆盖+二分。

  Description

  The country of jiuye composed by N cites. Each city can be viewed as a point in a two- dimensional plane with integer coordinates (x,y). The distance between city i and city j is defined by d ij = |x i - x j| + |y i - y j|. jiuye want to setup airport in K cities among N cities. So he need your help to choose these K cities, to minimize the maximum distance to the nearest airport of each city. That is , if we define d i(1 ≤ i ≤ N ) as the distance from city i to the nearest city with airport. Your aim is to minimize the value max{d i|1 ≤ i ≤ N }. You just output the minimum.

  题目是最大值最小化,明显的二分,然后对于每一个值,判断能不能找到K个以内的来覆盖。。。。。。

  做的时候要注意二分的问题,还有就是要用long long 别用int,还有就是abs。。。不知道怎么回事被坑了,自己写了一个abs来用的。。。。。。

#include<iostream>
#include<cstring>
#include<utility>
#include<algorithm>

using namespace std;

const int MaxN=70;
const int MaxM=70;
const int MaxNode=MaxN*MaxM;

int N,K;
long long X[70],Y[70];

long long abs1(long long x)
{
    if(x<0)
        x=-x;

    return x;
}

struct DLX
{
    int U[MaxNode],D[MaxNode],L[MaxNode],R[MaxNode],col[MaxNode];
    int S[MaxM],H[MaxN];
    int size,m,n;

    void init(int _n,int _m)
    {
        n=_n;
        m=_m;
        size=m;

        for(int i=0;i<=m;++i)
        {
            U[i]=D[i]=i;
            L[i]=i-1;
            R[i]=i+1;

            S[i]=0;
        }

        L[0]=m;
        R[m]=0;

        for(int i=0;i<=n;++i)
            H[i]=-1;
    }

    void Link(int r,int c)
    {
        col[++size]=c;
        ++S[c];

        U[size]=U[c];
        D[size]=c;
        D[U[c]]=size;
        U[c]=size;

        if(H[r]==-1)
            H[r]=L[size]=R[size]=size;
        else
        {
            L[size]=L[H[r]];
            R[size]=H[r];
            R[L[H[r]]]=size;
            L[H[r]]=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;
    }

    bool vis[MaxM];

    int getH()
    {
        int ret=0;

        for(int i=R[0];i;i=R[i])
            vis[i]=1;

        for(int c=R[0];c;c=R[c])
            if(vis[c])
            {
                ++ret;
                vis[c]=0;

                for(int i=D[c];i!=c;i=D[i])
                    for(int j=R[i];j!=i;j=R[j])
                        vis[col[j]]=0;
            }

        return ret;
    }

    bool Dance(int d)
    {
        if(d+getH()>K)
            return 0;

        if(R[0]==0)
            return d<=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(d+1))
                return 1;

            for(int j=L[i];j!=i;j=L[j])
                resume(j);

            resume(i);
        }

        return 0;
    }
};

pair <long long,int> rem[70][70];
long long remP[70];
DLX dlx;

void slove(long long maxNum)
{
    long long L=0,R=maxNum,M,ans;

    for(int i=1;i<=N;++i)
    {
        for(int j=1;j<=N;++j)
        {
            rem[i][j].first=(long long)abs1(X[i]-X[j])+(long long)abs1(Y[i]-Y[j]);
            rem[i][j].second=j;
        }

        sort(rem[i]+1,rem[i]+N+1);

        remP[i]=1;
    }

/*    dlx.init(N,N);

    for(M=L;M<=R;++M)
    {
        for(int i=1;i<=N;++i)
            while(rem[i][remP[i]].first<=M)
            {
                dlx.Link(i,rem[i][remP[i]].second);
                ++remP[i];
            }

        if(dlx.Dance(0))
            break;
    }*/

    while(R>L)
    {
        M=(L+R)/2;

        dlx.init(N,N);

        for(int i=1;i<=N;++i)
            for(int j=1;j<=N;++j)
                if(rem[i][j].first<=M)
                    dlx.Link(i,rem[i][j].second);
                else
                    break;

        if(dlx.Dance(0))
            R=M;
        else
            L=M+1;
    }

    cout<<L<<endl;
}

int main()
{
    ios::sync_with_stdio(false);

    int T;
    long long maxX,maxY,minX,minY;
    cin>>T;

    for(int cas=1;cas<=T;++cas)
    {
        cin>>N>>K;

        cin>>X[1]>>Y[1];

        maxX=minX=X[1];
        maxY=minY=Y[1];

        for(int i=2;i<=N;++i)
        {
            cin>>X[i]>>Y[i];

            if(maxX<X[i])
                maxX=X[i];

            if(maxY<Y[i])
                maxY=Y[i];

            if(minX>X[i])
                minX=X[i];

            if(minY>Y[i])
                minY=Y[i];
        }

        cout<<"Case #"<<cas<<": ";
        slove(maxX+maxY-minX-minY);
    }

    return 0;
}

时间: 2024-11-05 19:00:34

(中等) HDU 5046 Airport ,DLX+可重复覆盖+二分。的相关文章

HDU 5046 Airport ( Dancing Links 重复覆盖 )

今年上海网络赛的一道题目 , 跟 HDU 2295 如出一辙 , 就是距离的计算一个是欧几里得距离 , 一个是曼哈顿距离 学完DLX感觉这题好水 ,就是一个裸的重复覆盖 注意下别溢出就行了 #include <stdio.h> #include <string.h> #include <algorithm> #include <vector> #include <math.h> #include <stdlib.h> using na

HDU 3335 Divisibility(DLX可重复覆盖)

Problem Description As we know,the fzu AekdyCoin is famous of math,especially in the field of number theory.So,many people call him "the descendant of Chen Jingrun",which brings him a good reputation. AekdyCoin also plays an important role in th

HDU5046 Airport dancing links 重复覆盖+二分

这一道题和HDU2295是一样 是一个dancing links重复覆盖解决最小支配集的问题 在给定长度下求一个最小支配集,只要小于k就行 然后就是二分答案,每次求最小支配集 只不过HDU2295是浮点,这里是整数 我写的一个比较暴力 #include<cstdio> #include<cstring> #include<queue> #include<cstdlib> #include<algorithm> #include<vector

HDU 2295 舞蹈链可重复覆盖+二分

点击打开链接 题意:给了n个点和m个圆心,在用不多于k个圆的情况下,使得所有的点被覆盖,最小的圆半径多大 思路:问最小的什么什么那么用二分准没错,那么二分条件是什么呢,就是用不多于K的圆能否将所有点覆盖,覆盖这部分就是裸的舞蹈链的可重复覆盖,行为m个圆,列为n个点,然后求出的最少行小于等于K,则成立,否则不成立 #include <math.h> #include <vector> #include <stdio.h> #include <string.h>

HDU 5046 Airport(dlx)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5046 题意:n个城市修建m个机场,使得每个城市到最近进场的最大值最小. 思路:二分+dlx搜索判定. const int INF=1000000005; const int N=4444; int m; struct node { int L[N],R[N],D[N],U[N],e; int col[N]; int H[N],num[N]; int visit[N],KK; void init(in

HDU 5046 Airport ( Dancing Links 反复覆盖 )

今年上海网络赛的一道题目 , 跟 HDU 2295 如出一辙 . 就是距离的计算一个是欧几里得距离 , 一个是曼哈顿距离 学完DLX感觉这题好水 ,就是一个裸的反复覆盖 注意下别溢出即可了 #include <stdio.h> #include <string.h> #include <algorithm> #include <vector> #include <math.h> #include <stdlib.h> using na

hdu5064 DLX可重复覆盖+二分

这题题意是 给了n个城市 在其中小于等于k个城市建立机场然后 使得最远的那个离机场的城市距离最短 二分答案 ,我们对于每次的mid 重新建图然后再来一次DLX,每个点可以覆盖的点建立一条联系就ok了 #include <iostream> #include <algorithm> #include <cstdio> #include <string.h> #include <vector> using namespace std; const i

HDU 5046 Airport(DLX重复覆盖)

HDU 5046 Airport 题目链接 题意:给定一些机场,要求选出K个机场,使得其他机场到其他机场的最大值最小 思路:二分+DLX重复覆盖去判断即可 代码: #include <cstdio> #include <cstring> using namespace std; const int MAXNODE = 4005; const int MAXM = 65; const int MAXN = 65; const int INF = 0x3f3f3f3f; int K;

HDU 5046 Airport(DLX可重复覆盖)

Problem Description The country of jiuye composed by N cites. Each city can be viewed as a point in a two- dimensional plane with integer coordinates (x,y). The distance between city i and city j is defined by dij = |xi - xj| + |yi - yj|. jiuye want