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 }
View Code

 

你可能感兴趣的:(HDU)