[kuangbin]专题三 Dancing Links Radar HDU - 2295【二分】【重复覆盖】

本文介绍了一种使用二分查找和精确覆盖算法(DLX)来最小化雷达覆盖半径的方法,旨在用最少的雷达数量覆盖所有城市,适用于战争状态下的Java王国城市雷达部署问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目描述】
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.
Java王国的N座城市因为处于战争状态被雷达覆盖。由于王国有M个雷达站但是只有K个操作员,我们最多能操控K个雷达。所有雷达都有相同的覆盖半径R。我们的目标是最小化半径R用不超过K座雷达站使所有城市被雷达覆盖。

【输入】
The input consists of several test cases. The first line of the input consists of an integer T, indicating the number of test cases. The first line of each test case consists of 3 integers: N, M, K,representing the number of cities, the number of radar stations and the number of operators. Each of the following N lines consists of the coordinate of a city.
Each of the last M lines consists of the coordinate of a radar station.
All coordinates are separated by one space.
输入包含多个样例,第一行输入包含一个整数T表示样例的个数。每个样例的第一行包含3个整数N,M,K表示城市的数量,雷达站的数量和操作员的数量。后面N行表示城市的坐标。最后M行表示雷达站的坐标。所有坐标用空格隔开。
Technical Specification

  1. 1 ≤ T ≤ 20
  2. 1 ≤ N, M ≤ 50
  3. 1 ≤ K ≤ M
  4. 0 ≤ X, Y ≤ 1000

【输出】
For each test case, output the radius on a single line, rounded to six fractional digits.
对于每个样例,输出半径,保留6位小数。

【样例输入】
1
3 3 2
3 4
3 1
5 4
1 1
2 2
3 3

【样例输出】
2.236068

题目链接:https://cn.vjudge.net/problem/HDU-2295

二分半径+DLX判断+剪枝,kuangbin模板真好用

代码如下:

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
#define EPS 1e-8
static const int MAXN=50+5;
static const int MAXM=50+5;
static const int MAXNODE=MAXN*MAXM;
int sta_x[MAXM],sta_y[MAXM],city_x[MAXN],city_y[MAXN];
int k;
struct DLX{
    int n,m,size;
    int U[MAXNODE],D[MAXNODE],R[MAXNODE],L[MAXNODE],Row[MAXNODE],Col[MAXNODE];
    int H[MAXN],S[MAXM];
    int ansd,ans[MAXN];
    bool vis[MAXNODE];
    void init(int _n,int _m)
    {
        n=_n;
        m=_m;
        for(int i=0;i<=m;i++)
        {
            S[i]=0;
            U[i]=D[i]=i;
            L[i]=i-1;
            R[i]=i+1;
        }
        R[m]=0;
        L[0]=m;
        size=m;
        for(int i=1;i<=n;i++)
            H[i]=-1;
    }
    void Link(int r,int c)
    {
        ++S[Col[++size]=c];
        Row[size]=r;
        D[size]=D[c];
        U[D[c]]=size;
        U[size]=c;
        D[c]=size;
        if(H[r]<0)
            H[r]=L[size]=R[size]=size;
        else
        {
            R[size]=R[H[r]];
            L[R[H[r]]]=size;
            L[size]=H[r];
            R[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;
    }
    int f()
    {
        int res=0;
        for(int i=R[0];i!=0;i=R[i])
            vis[i]=true;
        for(int i=R[0];i!=0;i=R[i])
            if(vis[i])
            {
                res++;
                vis[i]=false;
                for(int j=D[i];j!=i;j=D[j])
                    for(int t=R[j];t!=j;t=R[t])
                        vis[Col[t]]=false;
            }
        return res;
    }
    bool Dance(int d)
    {
        if(d+f()>k)
            return false;
        if(R[0]==0)
            return d<=k;
        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 true;
            for(int j=L[i];j!=i;j=L[j])
                resume(j);
            resume(i);
        }
        return false;
    }
};
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        DLX dlx;
        int n,m;
        cin>>n>>m>>k;
        for(int i=0;i<n;i++)
            cin>>city_x[i]>>city_y[i];
        for(int i=0;i<m;i++)
            cin>>sta_x[i]>>sta_y[i];
        double l=0,r=0x7fffffff;
        while(r-l>=EPS)
        {
            dlx.init(m,n);
            double mid=(l+r)/2;
            for(int i=0;i<m;i++)
                for(int j=0;j<n;j++)
                    if(sqrt((sta_x[i]-city_x[j])*(sta_x[i]-city_x[j])+(sta_y[i]-city_y[j])*(sta_y[i]-city_y[j]))<mid-EPS)
                        dlx.Link(i+1,j+1);
            if(dlx.Dance(0))
                r=mid-EPS;
            else
                l=mid+EPS;               
        }
        cout.setf(ios::fixed);
        cout<<setprecision(6)<<l<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值