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; }