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

时间:2023-03-09 19:07:41
hdu 2295 dlx重复覆盖+二分答案

题目大意:

有一堆雷达工作站,安放至多k个人在这些工作站中,找到一个最小的雷达监控半径可以使k个工作人所在的雷达工作站覆盖所有城市

二分半径的答案,每次利用dlx的重复覆盖来判断这个答案是否正确

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <climits>
#include <cmath> using namespace std;
#define N 55
#define MAXNODE 3000
const double INF = 1e9;
const double eps = 1e-; int n,m,k; struct DLX{
int n,m,size;
int U[MAXNODE] , D[MAXNODE] , L[MAXNODE] , R[MAXNODE];
int col[MAXNODE] , row[MAXNODE];
int first[N] , cnt_col[N];
bool v[MAXNODE]; void init(int _n , int _m)
{
n = _n , m = _m , size = _m;
for(int i= ; i<=m ; i++){
U[i] = D[i] = i;
L[i] = i- , R[i] = i+;
col[i] = i , row[i] = ;
}
L[] = m , R[m] = ;
for(int i= ; i<=n ; i++) first[i] = -;
for(int i= ; i<=m ; i++) cnt_col[i] = ;
} void link(int r , int c)
{
++size;
U[D[c]] = size , D[size] = D[c];
U[size] = c , D[c] = size;
cnt_col[c]++; if(first[r]<) first[r] = L[size] = R[size] = size;
else{
R[size] = R[first[r]] , L[R[first[r]]] = size;
L[size] = first[r] , R[first[r]] = size;
}
row[size] = r , col[size] = c;
} 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 ret = ;
for(int c=R[] ; c!= ; c=R[c]) v[c]=true;
for(int c=R[] ; c!= ; c=R[c])
if(v[c]){
ret++;
v[c] = false;
for(int i=D[c] ; i!=c ; i=D[i])
for(int j=R[i] ; j!= i ; j=R[j])
v[col[j]]=false;
}
return ret;
} bool Dance(int d)
{
//这里k表示题目所给意思让我们至多在dlx中选择k行
if(d+f() > k) return false;
if(!R[]) return d<=k;
int st = R[];
for(int i=R[] ; i!= ; i=R[i])
if(cnt_col[st]>cnt_col[i]) st=i; for(int i=D[st] ; i!=st ; i=D[i]){
Remove(i);
for(int j=R[i] ; j!=i ; j=R[j]) Remove(j);
if(Dance(d+)) return true;
for(int j=L[i] ; j!=i ; j=L[j]) Resume(j);
Resume(i);
}
return false;
}
}dlx; struct Point{
double x,y;
}p1[N] , p2[N]; double getDis(int i , int j)
{
return sqrt((p1[i].x-p2[j].x)*(p1[i].x-p2[j].x)+(p1[i].y-p2[j].y)*(p1[i].y-p2[j].y));
} bool check(double mid)
{
dlx.init(m , n);
for(int i= ; i<=m ; i++){
for(int j=; j<=n ;j++){
if(getDis(j , i)<=mid) dlx.link(i,j);
}
}
return dlx.Dance();
} double bin_search()
{
double l= , r=INF;
while(r-l>eps){
double mid = (l+r)/;
if(check(mid)) r=mid;
else l=mid;
}
return r;
} int main()
{
// freopen("a.in" , "r" , stdin);
int T;
scanf("%d" , &T);
while(T--)
{
scanf("%d%d%d" , &n , &m , &k);
for(int i= ; i<=n ; i++)
scanf("%lf%lf" , &p1[i].x , &p1[i].y);
for(int i= ; i<=m ; i++)
scanf("%lf%lf" , &p2[i].x , &p2[i].y);
printf("%.6lf\n" , bin_search());
}
return ;
}