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
",ans);
134     }
135     return 0;
136 }
View Code