(中等) HDU 2295 , DLX+重复覆盖+二分。

  Description

  N cities of the Java Kingdom need to be covered by radars for being in a state of war. Since the kingdom has M radar stations but only K operators, we can at most operate K radars. All radars have the same circular coverage with a radius of R. Our goal is to minimize R while covering the entire city with no more than K radars.

  题目就是让我们找到一个最小的R,能够在M个站里面找到K个来覆盖N个城市。

  假设知道R的话,就可以通过DLX判断这个R成不成立,然后二分查找R就好。。。。。。

代码如下:

#include<iostream>
#include<cstring>

using namespace std;

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

int K;
int N,M;

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

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

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

            S[i]=0;
        }
        L[0]=m;
        R[m]=0;

        size=m;

        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])
        {
            R[L[i]]=R[i];
            L[R[i]]=L[i];
        }
    }

    void resume(int c)
    {
        for(int i=U[c];i!=c;i=U[i])
            R[L[i]]=L[R[i]]=i;
    }

    bool vis[MaxM];

    int getH()
    {
        int ret=0;

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

        for(int c=R[0];c!=0;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)
        {
            if(d<=K)
                return 1;
            return 0;
        }

        int c=R[0];

        for(int i=R[0];i!=0;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;
    }
};

DLX dlx;
int Rx[60],Ry[60],Cx[60],Cy[60];

void solve()
{
    double L=0,R=1001.0,Mid;

    while(R-L>0.0000001)
    {
        Mid=(L+R)/2;

        dlx.init(M,N);

        for(int i=1;i<=M;++i)
            for(int j=1;j<=N;++j)
                if(Mid*Mid>=(Rx[i]-Cx[j])*(Rx[i]-Cx[j])+(Ry[i]-Cy[j])*(Ry[i]-Cy[j]))
                    dlx.Link(i,j);

        if(dlx.Dance(0))
            R=Mid;
        else
            L=Mid;
    }

    cout<<L<<endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cout.setf(ios::fixed);
    cout.precision(6);

    int T;
    cin>>T;

    while(T--)
    {
        cin>>N>>M>>K;

        for(int i=1;i<=N;++i)
            cin>>Cx[i]>>Cy[i];

        for(int i=1;i<=M;++i)
            cin>>Rx[i]>>Ry[i];

        solve();
    }

    return 0;
}

时间: 2024-08-30 04:25:33

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

hdu 2295 dlx重复覆盖+二分答案

题目大意: 有一堆雷达工作站,安放至多k个人在这些工作站中,找到一个最小的雷达监控半径可以使k个工作人所在的雷达工作站覆盖所有城市 二分半径的答案,每次利用dlx的重复覆盖来判断这个答案是否正确 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 #include <climits

(中等) HDU 3335 , DLX+重复覆盖。

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 the ACM_D

hdu 2295 Radar 重复覆盖+二分

题目链接 给m个雷达, n个城市, 以及每个城市的坐标, m个雷达里只能使用k个, 在k个雷达包围所有城市的前提下, 求最小半径. 先求出每个雷达到所有城市的距离, 然后二分半径, 如果距离小于二分的值, 就加边(大概不叫加边, 我也不知道叫什么...... #include<bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair

[ACM] HDU 2295 Radar (二分+DLX 重复覆盖)

Radar Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2593    Accepted Submission(s): 1012 Problem Description N cities of the Java Kingdom need to be covered by radars for being in a state of

HDU 2295 DLX 二分

Radar Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2229    Accepted Submission(s): 888 Problem Description N cities of the Java Kingdom need to be covered by radars for being in a state of w

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;

[DLX重复覆盖] hdu 2828 Lamp

题意: 有N个灯M个开关 每个灯的ON和OFF状态都能控制一个灯是否亮 给出N行,代表对于每个灯 哪些开关的哪个状态可以使得第i个灯亮 思路: 这里需要注意一个问题 如果开关1的ON 状态和开关2的ON状态能使得1号灯亮 那么开关1.2同时处于ON的时候 1号灯也是亮的.意思就是只要有一个开关使得灯亮,灯就亮了. 简单的DLX 重复覆盖 行为每个开关的两个状态2*m行,列为n个灯 在搜索的同时标记一下哪个开关被用过了 那么另一个状态也不能用了 代码: #include"stdio.h"

hdu2295(重复覆盖+二分)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2295 题意::一个国家有n个城市,有m个地方可以建造雷达,最多可以建K个雷达(K>=1 && K<=m),问雷达最短的探测半径,才能使n个城市都能探测到. 分析:二分距离,然后再DLX重复覆盖来判断.n个城市排成n列,再将每个城市当成一行,在二分的距离内能到达的城市在该列标为1,然后问题就转换成选至多k行来覆盖所有列,并且是可重复覆盖. #include <cstdio>

FZU 1686 神龙的难题(DLX重复覆盖)

FZU 1686 神龙的难题 题目链接 题意:中文题 思路:每一个1看成列,每个位置作为左上角的矩阵看成行,dlx重复覆盖即可 代码: #include <cstdio> #include <cstring> using namespace std; const int MAXNODE = 66666; const int INF = 0x3f3f3f3f; const int MAXM = 230; const int MAXN = 230; int K; struct DLX