zoukankan      html  css  js  c++  java
  • 数学一本通——【计算几何】Minimal Circle(最小圆覆盖模板)

    Description
    You are to write a program to find a circle which covers a set of points and has the minimal area. There will be no more than 100 points in one problem.

    Input
    The input contains several problems. The first line of each problem is a line containing only one integer N which indicates the number of points to be covered. The next N lines contain N points. Each point is represented by x and y coordinates separated by a space. After the last problem, there will be a line contains only a zero.

    Output
    For each input problem, you should give a one-line answer which contains three numbers separated by spaces. The first two numbers indicate the x and y coordinates of the result circle, and the third number is the radius of the circle. (use escape sequence %.2f)

    Samples
    Input 复制
    2
    0.0 0.0
    3 0
    5
    0 0
    0 1
    1 0
    1 1
    2 2
    0
    Output
    1.50 0.00 1.50
    1.00 1.00 1.41

    代码:
    转自

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll>PLL;
    typedef pair<int,int>PII;
    typedef pair<double,double>PDD;
    #define I_int ll
    inline ll read()
    {
        ll x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*f;
    }
    #define read read()
    #define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    #define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i<(b);i++)
    #define per(i,a,b) for(int i=(a);i>=(b);i--)
    #define perr(i,a,b) for(int i=(a);i>(b);i--)
    ll ksm(ll a,ll b,ll p)
    {
        ll res=1;
        while(b)
        {
            if(b&1)res=res*a%p;
            a=a*a%p;
            b>>=1;
        }
        return res;
    }
    #define PI acos(-1)
    const double eps=1e-8;
    const int maxn=5100;
    #define EPS 1e-8
    
    struct point{
        double x, y;
    };
    int sgn(double x)
    {
        if (fabs(x) < EPS)
            return 0;
        return x < 0 ? -1 : 1;
    }
    double get_distance(const point a, const point b)//两点之间的距离
    {
        return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }
    point get_circle_center(const point a, const point b, const point c)//得到三角形外接圆的圆心
    {
        point center;
        double a1 = b.x - a.x;
        double b1 = b.y - a.y;
        double c1 = (a1 * a1 + b1 * b1) / 2.0;
        double a2 = c.x - a.x;
        double b2 = c.y - a.y;
        double c2 = (a2 * a2 + b2 * b2) / 2.0;
        double d = a1 * b2 - a2 * b1;
        center.x = a.x + (c1 * b2 - c2 * b1) / d;
        center.y = a.y + (a1 * c2 - a2 * c1) / d;
        return center;
    }
    //p表示定点, n表示顶点的个数, c代表最小覆盖圆圆心, r是半径
    void min_cover_circle(point *p, int n, point &c, double &r)//找最小覆盖圆(这里没有用全局变量p[], 因为是为了封装一个函数便于调用)
    {
        random_shuffle(p, p + n);//随机函数,使用了之后使程序更快点,也可以不用
        c = p[0];
        r = 0;
        for (int i = 1; i < n; i++)
        {
            if (sgn(get_distance(p[i], c) - r) > 0)//如果p[i]在当前圆的外面, 那么以当前点为圆心开始找
            {
                c = p[i];//圆心为当前点
                r = 0;//这时候这个圆只包括他自己.所以半径为0
                for (int j = 0; j < i; j++)//找它之前的所有点
                {
                    if (sgn(get_distance(p[j], c) - r) > 0)//如果之前的点有不满足的, 那么就是以这两点为直径的圆
                    {
                        c.x = (p[i].x + p[j].x) / 2.0;
                        c.y = (p[i].y + p[j].y) / 2.0;
                        r = get_distance(p[j], c);
                        for (int k = 0; k < j; k++)
                        {
                            if (sgn(get_distance(p[k], c) - r) > 0)//找新作出来的圆之前的点是否还有不满足的, 如果不满足一定就是三个点都在圆上了
                            {
                                c = get_circle_center(p[i], p[j], p[k]);
                                r = get_distance(p[i], c);
                            }
                        }
                    }
                }
            }
        }
    }
    point p[maxn];
    int main()
    {
        int n;
        point c; double r;
        while (~scanf("%d", &n) && n)
        {
            for (int i = 0; i < n; i++)
                scanf("%lf %lf", &p[i].x, &p[i].y);
            min_cover_circle(p, n, c, r);
            printf("%.2lf %.2lf %.2lf
    ", c.x, c.y, r);
        }
        return 0;
    }
    
    
  • 相关阅读:
    这篇是Mark刚写的文档,原文为http://blogs.technet.com/markrussinovich/archive/2009/11/03/3291024.aspx
    自动加域批处理脚本[转]
    一次moveuser的使用经历[转]
    How to create fully custom Role, User, Event, Resource classes for use with the Security and Scheduler modules
    VBS脚本批处理创建域用户【可自动设置用户密码,创建OU】[转]
    eXpress App Framework Team
    客户端【脚本】自动加入域[转]
    XAF 如何控制自定义按钮的使用权限[转]
    How to make crossthread calls. (多线程操控窗体控件之不可行)
    改变TFS本地映射路径.
  • 原文地址:https://www.cnblogs.com/OvOq/p/14853028.html
Copyright © 2011-2022 走看看