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


    最小圆覆盖

    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
    %f %f
    ",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
    ",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
  • 相关阅读:
    编译原理第一次作业
    【码制】关于原码,反码,补码的一些笔记和理解
    输出1到50以内的所有素数【C】
    方法和数组
    if条件判断和switch,for do while
    变量
    全选,删除,添加
    java基础
    二级联
    轮播图
  • 原文地址:https://www.cnblogs.com/Fighting-sh/p/10841368.html
Copyright © 2020-2023  润新知