hdu3124Arbiter(最小圆距离-扫描线)
详解http://blog.sina.com.cn/s/blog_6e7b12310100qnex.html
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 set<int>st; 18 struct point 19 { 20 double x,y,r; 21 point(double x = 0,double y = 0):x(x),y(y){} 22 int id; 23 }p[N],rank[N]; 24 struct line 25 { 26 double po; 27 int id; 28 }lef[N],rig[N]; 29 int rk[N],n,pp[N]; 30 double mid; 31 typedef point pointt; 32 point operator -(point a,point b) 33 { 34 return point(a.x-b.x,a.y-b.y); 35 } 36 int dcmp(double x) 37 { 38 if(fabs(x)<eps) return 0; 39 return x<0?-1:1; 40 } 41 double dis(point a) 42 { 43 return sqrt(a.x*a.x+a.y*a.y*1.0); 44 } 45 int is_cross(int a,int b) 46 { 47 double dd = dis(rank[a]-rank[b]); 48 if(dcmp(dd-rank[a].r-rank[b].r-mid-mid)>0) return 0; 49 return 1; 50 } 51 int judge(int a) 52 { 53 set<int>::iterator it=st.insert(a).first;//插入a后所在位置 54 if(it!=st.begin()) 55 { 56 if(is_cross(a,*--it)) 57 return 1; 58 it++; 59 } 60 if(++it!=st.end()) 61 { 62 if(is_cross(a,*it)) return 1; 63 } 64 return 0; 65 } 66 int cal() 67 { 68 st.clear(); 69 int i = 1,j = 1; 70 while(i<=n||j<=n) 71 { 72 if(j==n+1||(i!=n+1&&dcmp(lef[i].po-mid-(rig[j].po+mid))<=0))//如果当且i圆的最左端小于j圆的最右端 将i插进来 73 { 74 int ip = rk[lef[i].id]; 75 if(judge(ip)) 76 return 1; 77 i++; 78 } 79 else 80 { 81 st.erase(rk[rig[j].id]); 82 j++; 83 } 84 } 85 return 0; 86 } 87 double solve() 88 { 89 double low = 0.0,high = dis(p[1]-p[2])-p[1].r-p[2].r; 90 while(low+eps<high)//二分距离 91 { 92 mid = (high+low)/2; 93 if(cal()) 94 high = mid; 95 else low = mid; 96 } 97 return high+low; 98 } 99 bool cmp(line a,line b) 100 { 101 return a.po<b.po; 102 } 103 bool cmpp(point a,point b) 104 { 105 if(a.y==b.y) return a.x<b.x; 106 return a.y<b.y; 107 } 108 int main() 109 { 110 int t,i; 111 cin>>t; 112 while(t--) 113 { 114 scanf("%d",&n); 115 for(i = 1; i <=n ;i++) 116 { 117 scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].r); 118 lef[i].po = p[i].x-p[i].r;//每个圆的最左端 119 lef[i].id = i; 120 rig[i].po = p[i].x+p[i].r;//每个圆的最右端 121 rig[i].id = i; 122 rank[i] = p[i];//按y坐标排序 123 rank[i].id = i; 124 } 125 sort(lef+1,lef+n+1,cmp); 126 sort(rig+1,rig+n+1,cmp); 127 sort(rank+1,rank+n+1,cmpp); 128 for(i = 1; i <= n; i++) 129 { 130 rk[rank[i].id] = i;//每个圆按y坐标排序后位于第几 131 } 132 double ans = solve(); 133 printf("%.6f\n",ans); 134 } 135 return 0; 136 }