zoukankan      html  css  js  c++  java
  • [BZOJ 1336] [Balkan2002] Alien最小圆覆盖 【随机增量法】

    题目链接:BZOJ - 1336

    题目分析

    最小圆覆盖有一个算法叫做随机增量法,看起来复杂度像是 O(n^3) ,但是可以证明其实平均是 O(n) 的,至于为什么我不知道= =

    为什么是随机呢?因为算法进行前要将所有的点 random_shuffle 一次。为什么要这样做呢?因为这样就可以防止出题人用最坏情况卡掉增量算法。

    这和随机化快排使用随机是一个道理。

    算法步骤:

    random_shuffle n 个点
    将圆设定为以 P[1] 为圆心,以 0 为半径 
    for i : 1 to n
    {
    	if (P[i] 不在圆内) 
    	{
    		将圆设定为以 P[i] 为圆心,以 0 为半径 
    		for j : 1 to i - 1
    		{
    			if (P[j] 不在圆内) 
    			{
    				将圆设定为以 P[i]P[j] 为直径
    				for k : 1 to j - 1
    				{
    					if (P[k] 不在圆内)
    					{
    						将圆设定为 P[i],P[j],P[k] 的外接圆 
    					}
    				}
    			}
    		}
    	}
    }
    

      

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    #define Vector Point
    
    typedef double LF;
    
    const int MaxN = 100000 + 5;
    
    const LF Eps = 1e-12;
    
    int n;
    
    struct Point
    {
    	LF x, y;
    	Point() {}
    	Point(LF a, LF b)
    	{
    		x = a; y = b;
    	}
    } P[MaxN];
    
    Point operator + (Point p1, Point p2)
    {
    	return Point(p1.x + p2.x, p1.y + p2.y);
    }
    Point operator - (Point p1, Point p2)
    {
    	return Point(p1.x - p2.x, p1.y - p2.y);
    }
    Vector operator * (Vector v, LF t)
    {
    	return Vector(v.x * t, v.y * t);
    }
    Vector operator / (Vector v, LF t)
    {
    	return Vector(v.x / t, v.y / t);
    }
    
    inline LF Sqr(LF x) {return x * x;}
    inline LF gmax(LF a, LF b) {return a > b ? a : b;}
    
    inline LF Dis(Point p1, Point p2) 
    {
    	return sqrt(Sqr(p1.x - p2.x) + Sqr(p1.y - p2.y));
    }
    
    struct Circle
    {
    	Point o;
    	LF r;
    	Circle() {}
    	Circle(Point a, LF b) 
    	{
    		o = a; r = b;
    	}
    	bool Inside(Point p)
    	{
    		return Dis(p, o) - r <= Eps;
    	}
    } C;
    
    struct Line
    {
    	Point p;
    	Vector v;
    	Line() {}
    	Line(Point a, Vector b) 
    	{
    		p = a; v = b;
    	}
    } L1, L2;
    
    LF Cross(Vector v1, Vector v2) 
    {
    	return v1.x * v2.y - v2.x * v1.y;
    }
    
    Point Intersection(Line l1, Line l2) 
    {
    	Vector u = l2.p - l1.p;
    	LF t = Cross(l2.v, u) / Cross(l2.v, l1.v);
    	return l1.p + (l1.v * t);
    }
    
    Vector Change(Vector v) 
    {
    	return Vector(-v.y, v.x);
    }
    
    Line Verticle(Point p1, Point p2) 
    {
    	Line ret;
    	ret.p = (p1 + p2) / 2.0;
    	ret.v = Change(p2 - p1);
    	return ret;
    }
    
    int main() 
    {
    	srand(19981014);
    	scanf("%d", &n);
    	for (int i = 1; i <= n; ++i)
    		scanf("%lf%lf", &P[i].x, &P[i].y);
    	random_shuffle(P + 1, P + n + 1);
    	C.o = P[1];
    	C.r = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (C.Inside(P[i])) continue;
    		C.o = P[i]; C.r = 0;
    		for (int j = 1; j < i; ++j)
    		{
    			if (C.Inside(P[j])) continue;
    			C.o = (P[i] + P[j]) / 2.0;
    			C.r = Dis(C.o, P[j]);
    			for (int k = 1; k < j; ++k)
    			{
    				if (C.Inside(P[k])) continue;
    				L1 = Verticle(P[i], P[k]);
    				L2 = Verticle(P[j], P[k]);
    				C.o = Intersection(L1, L2);
    				C.r = Dis(C.o, P[k]);
    			}	
    		}
    	}
    	printf("%.10lf
    %.10lf %.10lf
    ", C.r, C.o.x, C.o.y);
    	return 0;
    }
    

      

  • 相关阅读:
    POJ1579Function Run Fun
    C++ 程序员必读书目清单
    zoj2100Seeding(水题)
    接口开发及技术负责
    哪些需求最重要
    地址
    哪些需求最重要
    setTimeOut与 setInterval区别
    项目管理简介
    项目管理简介
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4350420.html
Copyright © 2011-2022 走看看