2 条题解

  • 0
    @ 2026-7-4 8:46:20

    #include <cstdio>
    #include <algorithm>
    #include <ctime>
    #include <cmath>
    using namespace std;
    #define db double
    const int M = 100005;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n;
    struct point
    {
    	db x,y;
    	point(db X=0,db Y=0) : x(X) , y(Y) {}
    	point operator + (db t) {return point(x+t,y+t);}
    	point operator - (db t) {return point(x-t,y-t);}
    	point operator * (db t) {return point(x*t,y*t);}
    	point operator / (db t) {return point(x/t,y/t);}
    	point operator + (point r) {return point(x+r.x,y+r.y);}
    	point operator - (point r) {return point(x-r.x,y-r.y);}
    	point rotate() {return point(y,-x);}
    	db len() {return x*x+y*y;}
    }p[M];
    db cdt(point a,point b) {return a.x*b.x+a.y*b.y;}
    db crs(point a,point b) {return a.x*b.y-a.y*b.x;}
    point get(point a,point l0,point b,point l1)
    {
    	db k=crs(b-a,l1)/crs(l0,l1);
    	return a+l0*k;
    }
    point cir(point a,point b,point c)
    {
    	return get((a+b)/2,(b-a).rotate(),(b+c)/2,(c-b).rotate());
    }
    signed main()
    {
    	n=read();srand(time(0));
    	for(int i=1;i<=n;i++)
    		scanf("%lf %lf",&p[i].x,&p[i].y);
    	random_shuffle(p+1,p+1+n);
    	point o;db r=0;
    	for(int i=1;i<=n;i++)
    	{
    		if((p[i]-o).len()>r)
    		{
    			o=p[i];r=0;
    			for(int j=1;j<i;j++)
    				if((o-p[j]).len()>r)
    				{
    					o=(p[i]+p[j])/2;r=(o-p[j]).len();
    					for(int k=1;k<j;k++)
    						if((o-p[k]).len()>r)
    						{
    							o=cir(p[i],p[j],p[k]);
    							r=(o-p[k]).len();
    						}
    				}
    		}
    	}
    	printf("%.10f\n%.10f %.10f\n",sqrt(r),o.x,o.y);
    }
    
    
    • 0
      @ 2026-7-4 8:37:59

      G56 最小圆覆盖 随机增量法【计算几何】

      #include <iostream>
      #include <cstring>
      #include <algorithm>
      #include <cmath>
      #define x first
      #define y second
      using namespace std;
      
      const int N=100010;
      const double PI=acos(-1);
      int n;
      struct Point{double x,y;} p[N];
      struct Circle{Point p; double r;} C;
      
      Point operator+(Point a, Point b){
        return {a.x+b.x, a.y+b.y};
      }
      Point operator-(Point a, Point b){
        return {a.x-b.x, a.y-b.y};
      }
      Point operator*(Point a, double t){
        return {a.x*t, a.y*t};
      }
      Point operator/(Point a, double t){
        return {a.x/t, a.y/t};
      }
      double operator*(Point a, Point b){
        return a.x*b.y-a.y*b.x;
      }
      Point rotate(Point a, double b){
        return {a.x*cos(b)-a.y*sin(b),a.x*sin(b)+a.y*cos(b)};
      }
      double dis(Point a, Point b){
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
      }
      Point cross(Point a,Point u,Point b,Point v){ 
        double t=(a-b)*v/(v*u);
        return a+u*t; //直线交点
      }
      pair<Point, Point> midperp(Point a, Point b){
        return {(a+b)/2, rotate(b-a,PI/2)}; //中垂线
      }
      Circle cover(Point a, Point b){
        return {(a+b)/2, dis(a,b)/2}; //覆盖两点的圆
      }
      Circle cover(Point a, Point b, Point c){
        auto u=midperp(a, b), v=midperp(a, c);
        auto p=cross(u.x, u.y, v.x, v.y);
        return {p, dis(p, a)}; //覆盖三点的圆
      }
      void increment(){ //增量法
        C={p[1], 0};
        for(int i=2; i<=n; i++){
          if(C.r<dis(C.p, p[i])){
            C={p[i], 0}; //一点圆
            for(int j=1; j<i; j++){
              if(C.r<dis(C.p, p[j])){
                C=cover(p[i], p[j]); //两点圆
                for(int k=1; k<j; k++)
                  if(C.r<dis(C.p, p[k]))
                    C=cover(p[i],p[j],p[k]); //三点圆
              }
            }
          }
        }  
      }
      int main(){
        scanf("%d", &n);
        for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
        random_shuffle(p+1, p+n+1); //随机化
        increment(); //增量法
        printf("%.10lf\n%.10lf %.10lf\n", C.r, C.p.x, C.p.y);
        return 0;
      }
      
      • 1

      G56_1 最小圆覆盖 随机增量法【计算几何】 [Balkan2002]Alien最小圆覆盖[p1742]

      信息

      ID
      2989
      时间
      1000ms
      内存
      128MiB
      难度
      10
      标签
      递交数
      6
      已通过
      2
      上传者