ZOJ 1450 Minimal Circle 最小圆覆盖

89 篇文章 0 订阅
7 篇文章 0 订阅

经典的计算几何题目,最小圆覆盖。

最小的圆肯定落在三个点上,因此暴力枚举圆上的三个点即可。

点增量算法,复杂度O(n^3)

加入随机化,平均复杂度可以降到O(n^2)



三点的外接圆圆心的函数:

POINT circumcenter(POINT &a, POINT &b, POINT &c) {
    POINT ret;
    double a1=b.x-a.x, b1=b.y-a.y, c1=(a1*a1+b1*b1)/2;
    double a2=c.x-a.x, b2=c.y-a.y, c2=(a2*a2+b2*b2)/2;
    double d = a1*b2 - a2*b1;
    ret.x = a.x + (c1*b2-c2*b1)/d;
    ret.y = a.y + (a1*c2-a2*c1)/d;
    return ret;
}


这道题目在HDU上面也有,但是两道题目代码不能互相AC,应该是数据的原因,各种精度问题,还是看重算法吧,暂且把数据无视了。



#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define N 110
struct POINT {
    double x, y;
} p[N];
int n;
inline double dist(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 circumcenter(POINT &a, POINT &b, POINT &c) {
    POINT ret;
    double a1=b.x-a.x, b1=b.y-a.y, c1=(a1*a1+b1*b1)/2;
    double a2=c.x-a.x, b2=c.y-a.y, c2=(a2*a2+b2*b2)/2;
    double d = a1*b2 - a2*b1;
    ret.x = a.x + (c1*b2-c2*b1)/d;
    ret.y = a.y + (a1*c2-a2*c1)/d;
    return ret;
}
void solve() {
    random_shuffle(p, p+n);  //随机化序列,std里面的随机函数
    POINT c;
    double r = 0;
    for (int i=1; i<n; i++) {
        if (dist(p[i], c) <= r) continue;
        c = p[i];
        r = 0;
        for (int j=0; j<i; j++) {
            if (dist(p[j], c) <= r) continue;
            c.x = (p[i].x+p[j].x)/2;
            c.y = (p[i].y+p[j].y)/2;
            r = dist(p[j], c);
            for (int k=0; k<j; k++) {
                if (dist(p[k], c) <= r) continue;
                c = circumcenter(p[i], p[j], p[k]);
                r = dist(p[i], c);
            }
        }
    }
    printf("%.2lf %.2lf %.2lf\n", c.x, c.y, r);
}
int main() {
    while (scanf(" %d", &n) == 1 && n) {
        for (int i=0; i<n; i++)
            scanf(" %lf %lf", &p[i].x, &p[i].y);
        solve();
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值