• 【AHOI2012】信号塔


    题面

    题解

    xgzc怒切计算几何

    最小圆覆盖板子题

    整体算法如下:

    枚举第一个点,考虑当前圆是否包含了这个点,如果没有,则把圆变成以这个点为圆心,半径为(0)的圆。再枚举第二个点,考虑圆是否包含了这个点,如果没有,则把圆变成以这两个点的中点为圆心,半径为两点距离一半的圆。再枚举第三个点,节点是否在圆内,如果不在,则把圆直接变成这三个点的外接圆。

    (n^3)过百万???是的

    我们随机打乱点,这样的期望是(O(n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<cmath>
    #include<ctime>
    #include<algorithm>
    #define RG register
    #define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
    #define clear(x, y) memset(x, y, sizeof(x))
    
    inline int read()
    {
    	int data = 0, w = 1; char ch = getchar();
    	while(ch != '-' && (!isdigit(ch))) ch = getchar();
    	if(ch == '-') w = -1, ch = getchar();
    	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    const int maxn(1e6 + 10);
    const double eps(1e-10), pi(acos(-1));
    struct point { double x, y; };
    struct line { point a, v; };
    struct circle { point o; double r; } O;
    typedef point vector;
    inline vector operator + (const vector &lhs, const vector &rhs)
    	{ return (vector) {lhs.x + rhs.x, lhs.y + rhs.y}; }
    inline vector operator - (const vector &lhs, const vector &rhs)
    	{ return (vector) {lhs.x - rhs.x, lhs.y - rhs.y}; }
    inline vector operator * (const vector &lhs, const double &rhs)
    	{ return (vector) {lhs.x * rhs, lhs.y * rhs}; }
    inline vector operator / (const vector &lhs, const double &rhs)
    	{ return (vector) {lhs.x / rhs, lhs.y / rhs}; }
    inline double operator * (const vector &lhs, const vector &rhs)
    	{ return lhs.x * rhs.x + lhs.y * rhs.y; }
    inline double cross(const vector &lhs, const vector &rhs)
    	{ return lhs.x * rhs.y - lhs.y * rhs.x; }
    inline double Len(const vector &a) { return sqrt(a.x * a.x + a.y * a.y); }
    inline double Dis(const point &a, const point &b) { return Len(a - b); }
    inline vector rotate(const vector &lhs, const double &ang)
    {
    	double c = cos(ang), s = sin(ang);
    	return (vector) {lhs.x * c - lhs.y * s, lhs.x * s + lhs.y * c};
    }
    
    point Intersection(const line &a, const line &b)
    {
    	vector c = b.a - a.a;
    	double t = cross(b.v, c) / cross(b.v, a.v);
    	return a.a + a.v * t;
    }
    
    line half(const line &a)
    {
    	point b = a.a + a.v * .5;
    	return (line) {b, rotate(a.v, pi * .5)};
    }
    
    void getCircle(point p[], int n)
    {
    	std::random_shuffle(p + 1, p + n + 1);
    	for(RG int i = 1; i <= n; ++i)
    		if(Dis(O.o, p[i]) > O.r)
    		{
    			O.o = p[i], O.r = 0;
    			for(RG int j = 1; j < i; j++)
    				if(Dis(O.o, p[j]) > O.r)
    				{
    					O.o = (p[i] + p[j]) * .5, O.r = Dis(p[i], p[j]) * .5;
    					for(RG int k = 1; k < j; k++)
    						if(Dis(O.o, p[k]) > O.r)
    							O.o = Intersection(half((line) {p[i], p[j] - p[i]}),
    									half((line) {p[i], p[k] - p[i]})),
    							O.r = Dis(O.o, p[i]);
    				}
    		}
    	printf("%.2lf %.2lf %.2lf
    ", O.o.x, O.o.y, O.r);
    }
    
    int n; point p[maxn];
    int main()
    {
    	srand(time(NULL)); scanf("%d", &n);
    	for(RG int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
    	getCircle(p, n);
    	return 0;
    }
    
  • 相关阅读:
    gdal source code c++ make windows
    libjpeg安装和使用
    window 安装gdal和python
    gdal和python在windows上的安装
    将博客搬至CSDN
    ue4 Worldmachine 结合使用
    织梦学习
    前端 css html js javascript jquery
    jquery 表单验证插件
    gif动图生成
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10336956.html
Copyright © 2020-2023  润新知