zoukankan      html  css  js  c++  java
  • P1742 最小圆覆盖

    (color{#0066ff}{题目描述})

    给出N个点,让你画一个最小的包含所有点的圆。

    (color{#0066ff}{输入格式})

    先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0)

    (color{#0066ff}{输出格式})

    输出圆的半径,及圆心的坐标,保留10位小数

    (color{#0066ff}{输入样例})

    6
    8.0 9.0
    4.0 7.5
    1.0 2.0
    5.1 8.7
    9.0 2.0
    4.5 1.0
    

    (color{#0066ff}{输出样例})

    5.0000000000
    5.0000000000 5.0000000000
    

    (color{#0066ff}{数据范围与提示})

    none

    (color{#0066ff}{题解})

    随机增量法

    前置知识,三点定圆

    设圆上有三个点(A(x_1, y_1), B(x_2, y_2), C(x_3, y_3))

    我们可以找这些点的连线的任两条线,找它们垂直平分线的交点就是圆心

    易得向量(线段)AB,BC

    设两条线段的垂直平分线为(A_1x+B_1y=C_1,A_2x+B_2y=C_2)

    上式的A和B分别是两个向量的x和y(法向量(可以带入验证))

    之后带入AB,BC的中点来求出两个C

    联立两个垂直平分线,解出来

    (x=frac{C_2*B_1-C_1*B_2}{A_2*B_1-A_1*B_2}, y=frac{C_2*A_1-C_1*A_2}{B_2*A_1-B_1*A_2})

    有了圆心,半径自然好求,随便找圆上一点(A,B,C)与圆心求距离就是半径了

    随机增量

    初始设置第一个点为圆心,半径为0

    依次扫每个点,如果不在当前圆内,则以那个点为圆心

    再次扫从头开始到当前的每个点,如果不在当前圆中

    则当前点与那个点作为新圆直径,构成当前圆,再次扫到当前每个点

    如果仍有不在圆内的,三点定圆

    #include <bits/stdc++.h>
    #define _ 0
    #define LL long long
    inline LL in() {
    	LL x = 0, f = 1; char ch;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
    	return x * f;
    }
    const int maxn = 1e5 + 10;
    const double eps = 1e-14;
    struct node {
    	double x, y;
    	node(double x = 0, double y = 0)
    		:x(x), y(y) {}
    	double mod() {
    		return sqrt(x * x + y * y);
    	}
    	friend node operator - (const node &a, const node &b) {
    		return node(a.x - b.x, a.y - b.y);
    	}
    	friend node operator + (const node &a, const node &b) {
    		return node((a.x + b.x) / 2.0, (a.y + b.y) / 2.0);
    	}
    }e[maxn];
    int n;
    
    void circle(node a, node b, node c, node &o, double &r) {
    	node ab = b - a, bc = c - b, mid1 = a + b, mid2 = b + c;
    	double A1 = ab.x, B1 = ab.y, A2 = bc.x, B2 = bc.y;
    	double C1 = A1 * mid1.x + B1 * mid1.y, C2 = A2 * mid2.x + B2 * mid2.y;
    	o = node((C2 * B1 - C1 * B2) / (A2 * B1 - A1 * B2), (C2 * A1 - C1 * A2) / (B2 * A1 - B1 * A2));r = (o - a).mod(); 
    }
    
    void work() {
    	node o = e[1];
    	double r = 0;
    	for(int i = 2; i <= n; i++)
    		if((e[i] - o).mod() - r > eps) { 
    			o = e[i], r = 0;
    			for(int j = 1; j <= i - 1; j++)
    				if((e[j] - o).mod() - r > eps) {
    					o = e[i] + e[j];
    					r = (o - e[i]).mod();
    					for(int k = 1; k <= j - 1; k++)
    						if((e[k] - o).mod() - r > eps)
    							circle(e[i], e[j], e[k], o, r);
    				}
    		}
    	printf("%.10f
    %.10f %.10f", r, o.x, o.y);
    }
    
    int main() {
    	n = in();
    	for(int i = 1; i <= n; i++) scanf("%lf%lf", &e[i].x, &e[i].y);
    	work();
    	return 0;
    }
    
  • 相关阅读:
    BestCoder Round #65
    Codeforces Round #334 (Div. 2)
    二叉搜索树(排序二叉树)
    二叉搜索树 POJ 2418 Hardwood Species
    差分约束系统 POJ 3169 Layout
    思维题(转换) HDU 4370 0 or 1
    SPFA+Dinic HDOJ 3416 Marriage Match IV
    图论 SRM 674 Div1 VampireTree 250
    SPFA(建图) HDOJ 4725 The Shortest Path in Nya Graph
    SPFA(负环) LightOJ 1074 Extended Traffic
  • 原文地址:https://www.cnblogs.com/olinr/p/10187221.html
Copyright © 2011-2022 走看看