ZOJ 1450 HDU 3007 (最小圆覆盖)

首先这个圆边上必有至少两点,打乱数组,然后利用枚举,不断重新定义圆,找出最小的圆

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

const int N = 100005;
const double eps = 1e-8;

int n;

struct Point {
    double x, y;
    Point() {}
    Point(double x, double y) {
        this->x = x;
        this->y = y;
    }
    void read() {
        scanf("%lf%lf", &x, &y);
    }
} p[N];

struct Line {
    Point a, b;
    Line() {}
    Line(Point a, Point b) {
        this->a = a;
        this->b = b;
    }
};

typedef Point Vector;

Vector operator + (Vector A, Vector B) {
    return Vector(A.x + B.x, A.y + B.y);
}

Vector operator - (Vector A, Vector B) {
    return Vector(A.x - B.x, A.y - B.y);
}

Vector operator * (Vector A, double p) {
    return Vector(A.x * p, A.y * p);
}

Vector operator / (Vector A, double p) {
    return Vector(A.x / p, A.y / p);
}

double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;}

int dcmp(double x) {
    return x < -eps ? -1 : x > eps;
}

double dis(Point a, Point b) {
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}

Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) {
    Vector u = P - Q;
    double t = Cross(w, u) / Cross(v, w);
    return P + v * t;
}

Point CircumcircleOfTriangle(Point a, Point b, Point c) {
    Line u,v;
    u.a.x = (a.x + b.x) / 2;
    u.a.y = (a.y + b.y) / 2;
    u.b.x = u.a.x + (u.a.y - a.y);
    u.b.y = u.a.y - (u.a.x - a.x);
    v.a.x = (a.x + c.x) / 2;
    v.a.y = (a.y + c.y) / 2;
    v.b.x = v.a.x + (v.a.y - a.y);
    v.b.y = v.a.y - (v.a.x - a.x);
    return GetLineIntersection(u.a, u.b - u.a, v.a, v.b - v.a);
}

void Mincir() {
    random_shuffle(p, p + n);
    Point cir = p[0]; double r = 0;
    for (int i = 1; i < n; i++) {
        if (dcmp(dis(cir, p[i]) - r) <= 0) continue;
        cir = p[i]; r = 0;
        for (int j = 0; j < i; j++) {
            if(dcmp(dis(cir, p[j]) - r) <= 0) continue;
            cir.x = (p[i].x + p[j].x) / 2;
            cir.y = (p[i].y + p[j].y) / 2;
            r = dis(cir, p[j]);
            for (int k = 0; k < j; k++) {
                if (dcmp(dis(cir, p[k]) - r) <= 0) continue;
                cir = CircumcircleOfTriangle(p[i], p[j], p[k]);
                r = dis(cir, p[k]);
            }
        }
    }
    printf("%.2f %.2f %.2f\n", cir.x, cir.y, r);
}

int main() {
    while (~scanf("%d", &n) && n) {
        for (int i = 0; i < n; i++)
            p[i].read();
        Mincir();
    }
    return 0;
}
时间: 2024-11-11 06:10:28

ZOJ 1450 HDU 3007 (最小圆覆盖)的相关文章

ZOJ 1450 Minimal Circle 最小圆覆盖

套了个模板直接上,貌似没有随机化序列 QAQ //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring> #include <cmath> #include <stack> #include <queue> #include <

最小圆覆盖 hdu 3007

今天学习了一下最小圆覆盖, 看了一下午都没看懂, 晚上慢慢的摸索这代码,接合着别人的讲解, 画着图跟着代码一步一步的走着,竟然有些理解了. 最小圆覆盖: 给定n个点, 求出半径最小的圆可以把这些点全部包围, 可以在圆的边界上 下面是我的个人理解. 如果不对, 还请路过大牛指出 先找一个点, 让圆心等于这个点的坐标, 半径等于0, 显然这个对的, 接着找下一个点, 如果只有两个点的话, 那么最小的圆一定是以他们为直径做圆, 接着找第三个点, 如果第三个点在园内或者在边界上, 那么不用更新当前的最小

HDU 3007 Buried memory 最小圆覆盖

题目大意:没看.反正就是求最小圆覆盖. 思路:一个神奇的算法--随机增量法.可以证明,这个算法可以在O(n)的时间复杂度内求出最小圆覆盖.虽然好像能卡掉的样子,但是加上一句random_shuffle就卡不掉了. 具体的过程是这样的: 在全局记录一个圆,表示目前的最小圆覆盖.从头开始扫描.遇到第一个不在当前最小圆覆盖内的点的时候: 将这个点与当前最小圆覆盖的圆心为直径做一个圆,作为当前的最小圆覆盖.从头开始扫描.遇到第一个不在当前最小圆覆盖的点的时候: 将刚才的两个点和当前点做三角形,将这个三角

HDOJ 3007 Buried memory 增量法最小圆覆盖

增量法最小圆覆盖,简单模版 Buried memory Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2541    Accepted Submission(s): 1365 Problem Description Each person had do something foolish along with his or her g

ZOJ 1450

最小圆覆盖 #include <iostream> #include <algorithm> #include <cstdio> #include <cmath> using namespace std; const double eps=0.00000001; struct point { double x,y; }p[110]; struct circle{ point cent; double rad; }cir; int n; double Tria

HDU 3007

基本小圆覆盖模板题 #include <iostream> #include <algorithm> #include <cmath> using namespace std; int X,Y; int n; const double eps=0.00000001; struct point{ double x,y; }p[550]; struct Circle{ point cent; double r; }cir; double dist(point x, poin

HDOJ 2215 Maple trees 最小圆覆盖

增量法最小圆覆盖.... Maple trees Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1646    Accepted Submission(s): 510 Problem Description There are a lot of trees in HDU. Kiki want to surround all the t

POJ 2777 &amp;&amp; ZOJ 1610 &amp;&amp;HDU 1698 --线段树--区间更新

直接将这3题 放一起了  今天在做线段树的东西 这3个都是区间更新的 查询方式互相不同 反正都可以放到一起吧 直接先上链接了 touch me touch me touch me 关于涉及到区间的修改 -- 区间更新的话 分为 增减 或者 修改 主要就是个 laze 标记 就是延迟更新 对于区间更新的写法 一般是有2种 其一 仔细划分到每个细小的区间    另一 粗略划分 反正 ==我的代码里会给出2种写法 看自己喜好 hdu 1 //线段树 成段更新 ---> 替换 根结点的查询 2 3 #i

【BZOJ-1336&amp;1337】Alie最小圆覆盖 最小圆覆盖(随机增量法)

1336: [Balkan2002]Alien最小圆覆盖 Time Limit: 1 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1573  Solved: 697[Submit][Status][Discuss] Description 给出N个点,让你画一个最小的包含所有点的圆. Input 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0) Outpu