最小圆覆盖(随机增量||模拟退火)

最小圆覆盖

https://www.lydsy.com/JudgeOnline/problem.php?id=1337

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 1464  Solved: 737
[Submit][Status][Discuss]

Description

给出平面上N个点,N<=10^5.请求出一个半径最小的圆覆盖住所有的点

Input

第一行给出数字N,现在N行,每行两个实数x,y表示其坐标.

Output

输出最小半径,输出保留三位小数.

Sample Input

4
1 0
0 1
0 -1
-1 0

Sample Output

1.000

 

ac1() 模拟退火,ac2()随机增量法

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<vector>
  5 #include<cmath>
  6 #include<algorithm>
  7 using namespace std;
  8 const double eps=1e-8;
  9 const double INF=1e20;
 10 const double PI=acos(-1.0);
 11 
 12 
 13 ///pick定理:面积=内部格点数+(边上格点数/2)-1
 14 
 15 int sgn(double x){
 16     if(fabs(x)<eps) return 0;
 17     if(x<0) return -1;
 18     else return 1;
 19 }
 20 
 21 inline double sqr(double x){return x*x;}
 22 inline double hypot(double a,double b){return sqrt(a*a+b*b);}
 23 struct Point{
 24     double x,y;
 25     Point(){}
 26     Point(double _x,double _y){
 27         x=_x;
 28         y=_y;
 29     }
 30     void input(){
 31         scanf("%lf %lf",&x,&y);
 32     }
 33     Point operator - (const Point &b)const{
 34         return Point(x-b.x,y-b.y);
 35     }
 36     //叉积
 37     double operator ^ (const Point &b)const{
 38         return x*b.y-y*b.x;
 39     }
 40     //点积
 41     double operator * (const Point &b)const{
 42         return x*b.x+y*b.y;
 43     }
 44     //返回长度
 45     double len(){
 46         return hypot(x,y);
 47     }
 48     //返回两点的距离
 49     double distance(Point p){
 50         return hypot(x-p.x,y-p.y);
 51     }
 52     Point operator + (const Point &b)const{
 53         return Point(x+b.x,y+b.y);
 54     }
 55     Point operator * (const double &k)const{
 56         return Point(x*k,y*k);
 57     }
 58     Point operator / (const double &k)const{
 59         return Point(x/k,y/k);
 60     }
 61 
 62     //逆时针转90度
 63     Point rotleft(){
 64         return Point(-y,x);
 65     }
 66 };
 67 
 68 struct Line{
 69     Point s,e;
 70     Line(){}
 71     Line(Point _s,Point _e){
 72         s=_s;
 73         e=_e;
 74     }
 75     //根据一个点和倾斜角angle确定直线,0<=angle<pi
 76     Line(Point p,double angle){
 77         s=p;
 78         if(sgn(angle-PI/2)==0){
 79             e=(s+Point(0,1));
 80         }
 81         else{
 82             e=(s+Point(1,tan(angle)));
 83         }
 84     }
 85     //ax+by+c=0;
 86     Line(double a,double b,double c){
 87         if(sgn(a)==0){
 88             s=Point(0,-c/b);
 89             e=Point(1,-c/b);
 90         }
 91         else if(sgn(b)==0){
 92             s=Point(-c/a,0);
 93             e=Point(-c/a,1);
 94         }
 95         else{
 96             s=Point(0,-c/b);
 97             e=Point(1,(-c-a)/b);
 98         }
 99     }
100 
101     //求两直线的交点
102     //要保证两直线不平行或重合
103     Point crosspoint(Line v){
104         double a1=(v.e-v.s)^(s-v.s);
105         double a2=(v.e-v.s)^(e-v.s);
106         return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
107     }
108 };
109 
110 struct circle{
111     Point p;
112     double r;
113     circle(){}
114     circle(Point _p,double _r){
115         p=_p;
116         r=_r;
117     }
118 
119     circle(double x,double y,double _r){
120         p=Point(x,y);
121         r=_r;
122     }
123 
124     circle(Point a,Point b,Point c){///三角形的外接圆
125         Line u=Line((a+b)/2,((a+b)/2)+((b-a).rotleft()));
126         Line v=Line((b+c)/2,((b+c)/2)+((c-b).rotleft()));
127         p=u.crosspoint(v);
128         r=p.distance(a);
129     }
130 
131 
132 };
133 
134 Point p[100005];
135 int n;
136 
137 void ac2(){
138     random_shuffle(p+1,p+n+1);
139     circle c(p[1],0);
140     for(int i=1;i<=n;i++){
141         if(sgn((c.p-p[i]).len()-c.r)>0){
142             c.p=p[i],c.r=0;
143             for(int j=1;j<i;j++){
144                 if(sgn((c.p-p[j]).len()-c.r)>0){
145                     c.p=(p[i]+p[j])/2;
146                     c.r=(c.p-p[j]).len();
147                     for(int k=1;k<j;k++){
148                         if(sgn((c.p-p[k]).len()-c.r)>0){
149                             c=circle(p[i],p[j],p[k]);
150                         }
151                     }
152                 }
153             }
154         }
155     }
156     printf("%f\n%f %f\n",c.r,c.p.x,c.p.y);
157 }
158 
159 double dist(Point a,Point b){
160     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
161 }
162 
163 void ac1(){
164 
165     double ans=1e99;
166     Point tmp;
167     tmp.x=tmp.y=0;
168     int s=1;
169     double step=10000;
170     double esp=0.000001;
171     while(step>esp){
172         for(int i=1;i<=n;i++){
173             if(dist(tmp,p[s])<dist(tmp,p[i])) s=i;
174         }
175         double Dist=dist(tmp,p[s]);
176         ans=min(ans,Dist);
177         tmp.x+=(p[s].x-tmp.x)/Dist*step;
178         tmp.y+=(p[s].y-tmp.y)/Dist*step;
179         step*=0.98;
180     }
181     printf("%.3f\n",ans);
182 }
183 int main(){
184 
185     scanf("%d",&n);
186         for(int i=1;i<=n;i++){
187             p[i].input();
188         }
189         ac1();
190 
191     return 0;
192 }
View Code

 

posted on 2019-05-09 21:59  Fighting_sh  阅读(440)  评论(0编辑  收藏  举报

导航