N个城市,M个雷达站,最多可开K个雷达工作,给出城市和雷达的坐标,问雷达的工作半径最少为多少可以满足要求?
直接二分距离,判断当前距离K个雷达站是否能覆盖全部城市,判断的时候可以用DLX来搜,建立M行*N列的01矩阵,行表示雷达站,列表示城市,由于允许多个雷达站覆盖一个城市的情况,所以这题跟精确覆盖的实现还不太一样,remove和resume要改一下。另外这题裸上还会TLE,所以在搜索的时候要加个A*剪枝,估价函数的含义大致就是在当前的状态下,最少需要多少行才有可能覆盖所有的城市(注意这个数只是个下界,不是确定的值),那么若当前启动的雷达数+估价超过了限制的话,就可以剪掉了...
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxr=55;
const int maxc=55;
const int maxn=maxr*maxc;
const int inf=(1<<28);
int col[maxn],row[maxn],ans[maxn];
int S[maxc],H[maxr];
int size,cnt;
int U[maxn],D[maxn],L[maxn],R[maxn];
int g[maxr][maxc];
struct PT
{
double x,y;
}city[55],radar[55];
int n,m,k;
struct DLX
{
int h()
{
bool hs[55];
memset(hs,0,sizeof hs);
int ret=0;
for (int i=R[0]; i!=0; i=R[i])
{
if (!hs[i])
{
ret++;
hs[i]=true;
for (int j1=D[i]; j1!=i; j1=D[j1])
for (int j2=R[j1]; j2!=j1; j2=R[j2])
hs[col[j2]]=true;
}
}
return ret;
}
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]]=i;
R[L[i]]=i;
}
}
bool dfs(int p)
{
if (p+h()>k) return false;
if (p>k) return false;
int c=R[0];
if (c==0)
{
cnt=p;
return true;
}
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 (dfs(p+1)) return true;
for (int j=L[i]; j!=i; j=L[j]) resume(j);
resume(i);
}
return false;
}
void init(int m)
{
for (int i=0; i<=m; i++)
{
S[i]=0;
R[i]=i+1;
L[i]=i-1;
U[i]=D[i]=i;
}
L[0]=m;
R[m]=0;
size=m+1;
memset(H,-1,sizeof H);
}
void link(int x,int y)
{
++S[col[size]=y];
row[size]=x;
D[size]=D[y];
U[D[y]]=size;
U[size]=y;
D[y]=size;
if (H[x]<0) H[x]=L[size]=R[size]=size;
else
{
R[size]=R[H[x]];
L[R[H[x]]]=size;
L[size]=H[x];
R[H[x]]=size;
}
size++;
}
}dlx;
double dis(PT p, PT q)
{
return sqrt((double)((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y)));
}
void init(double limit)
{
memset(g,false,sizeof g);
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
if (dis(radar[i],city[j])<=limit) g[i][j]=true;
}
int main()
{
// freopen("in.txt","r",stdin);
int tt;
scanf("%d",&tt);
while (tt--)
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1; i<=n; i++)
scanf("%lf%lf",&city[i].x,&city[i].y);
for (int i=1; i<=m; i++)
scanf("%lf%lf",&radar[i].x,&radar[i].y);
double l=0.0,r=sqrt(1000.0*1000.0*2.0);
double mid;
while(fabs(l-r)>1e-8)
{
mid=(l+r)/2.0;
init(mid);
dlx.init(n);
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
if (g[i][j]) dlx.link(i,j);
cnt=inf;
if (dlx.dfs(0)) r=mid;
else l=mid;
}
printf("%.6lf\n",l);
}
return 0;
}