题目大意:
有一堆雷达工作站,安放至多k个人在这些工作站中,找到一个最小的雷达监控半径可以使k个工作人所在的雷达工作站覆盖所有城市
二分半径的答案,每次利用dlx的重复覆盖来判断这个答案是否正确
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 #include <climits> 7 #include <cmath> 8 9 using namespace std; 10 #define N 55 11 #define MAXNODE 3000 12 const double INF = 1e9; 13 const double eps = 1e-8; 14 15 int n,m,k; 16 17 struct DLX{ 18 int n,m,size; 19 int U[MAXNODE] , D[MAXNODE] , L[MAXNODE] , R[MAXNODE]; 20 int col[MAXNODE] , row[MAXNODE]; 21 int first[N] , cnt_col[N]; 22 bool v[MAXNODE]; 23 24 void init(int _n , int _m) 25 { 26 n = _n , m = _m , size = _m; 27 for(int i=0 ; i<=m ; i++){ 28 U[i] = D[i] = i; 29 L[i] = i-1 , R[i] = i+1; 30 col[i] = i , row[i] = 0; 31 } 32 L[0] = m , R[m] = 0; 33 for(int i=1 ; i<=n ; i++) first[i] = -1; 34 for(int i=1 ; i<=m ; i++) cnt_col[i] = 0; 35 } 36 37 void link(int r , int c) 38 { 39 ++size; 40 U[D[c]] = size , D[size] = D[c]; 41 U[size] = c , D[c] = size; 42 cnt_col[c]++; 43 44 if(first[r]<0) first[r] = L[size] = R[size] = size; 45 else{ 46 R[size] = R[first[r]] , L[R[first[r]]] = size; 47 L[size] = first[r] , R[first[r]] = size; 48 } 49 row[size] = r , col[size] = c; 50 } 51 52 void Remove(int c) 53 { 54 for(int i=D[c] ; i!=c ; i=D[i]){ 55 L[R[i]] = L[i] , R[L[i]] = R[i]; 56 } 57 } 58 59 void Resume(int c) 60 { 61 for(int i=U[c] ; i!=c ; i=U[i]){ 62 L[R[i]] = R[L[i]] = i; 63 } 64 } 65 66 int f() 67 { 68 int ret = 0; 69 for(int c=R[0] ; c!=0 ; c=R[c]) v[c]=true; 70 for(int c=R[0] ; c!=0 ; c=R[c]) 71 if(v[c]){ 72 ret++; 73 v[c] = false; 74 for(int i=D[c] ; i!=c ; i=D[i]) 75 for(int j=R[i] ; j!= i ; j=R[j]) 76 v[col[j]]=false; 77 } 78 return ret; 79 } 80 81 bool Dance(int d) 82 { 83 //这里k表示题目所给意思让我们至多在dlx中选择k行 84 if(d+f() > k) return false; 85 if(!R[0]) return d<=k; 86 int st = R[0]; 87 for(int i=R[0] ; i!=0 ; i=R[i]) 88 if(cnt_col[st]>cnt_col[i]) st=i; 89 90 for(int i=D[st] ; i!=st ; i=D[i]){ 91 Remove(i); 92 for(int j=R[i] ; j!=i ; j=R[j]) Remove(j); 93 if(Dance(d+1)) return true; 94 for(int j=L[i] ; j!=i ; j=L[j]) Resume(j); 95 Resume(i); 96 } 97 return false; 98 } 99 }dlx; 100 101 struct Point{ 102 double x,y; 103 }p1[N] , p2[N]; 104 105 double getDis(int i , int j) 106 { 107 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)); 108 } 109 110 bool check(double mid) 111 { 112 dlx.init(m , n); 113 for(int i=1 ; i<=m ; i++){ 114 for(int j=1; j<=n ;j++){ 115 if(getDis(j , i)<=mid) dlx.link(i,j); 116 } 117 } 118 return dlx.Dance(0); 119 } 120 121 double bin_search() 122 { 123 double l=0 , r=INF; 124 while(r-l>eps){ 125 double mid = (l+r)/2; 126 if(check(mid)) r=mid; 127 else l=mid; 128 } 129 return r; 130 } 131 132 int main() 133 { 134 // freopen("a.in" , "r" , stdin); 135 int T; 136 scanf("%d" , &T); 137 while(T--) 138 { 139 scanf("%d%d%d" , &n , &m , &k); 140 for(int i=1 ; i<=n ; i++) 141 scanf("%lf%lf" , &p1[i].x , &p1[i].y); 142 for(int i=1 ; i<=m ; i++) 143 scanf("%lf%lf" , &p2[i].x , &p2[i].y); 144 printf("%.6lf " , bin_search()); 145 } 146 return 0; 147 }