最小圆覆盖学习

今天学习最小圆覆盖。

算法

实际上算法就三个循环。
%%%!

void solve(){
    for( int i = 1 ; i <= N ; i ++ )
    if( !inside( p[i] ) ){
        O = p[i] ; R = 0 ;
        for( int j = 1 ; j < i ; j ++ )
        if( !inside( p[j] ) ){
            O = ( p[i] + p[j] ) / 2 ;
            R = dis( p[i] , O ) ;
            for( int k = 1 ; k < j ; k ++ )
            if( !inside( p[k] ) ){
                O = cal( p[i] , p[j] , p[k] ) ;
                R = dis( p[i] , O ) ;
            }
        }
    }
    	printf( "%f\n" , R ) ;
	    printf( "%f %f\n" , O.x , O.y ) ;
	}

复杂度分析

正确性分析

首先假设我们求出了i个点的最小圆覆盖
显然如果第i+1个点在里面就忽略
否则第i+1个点一定在圆上(可以用凸包的性质考虑)
最小圆覆盖学习_第1张图片
然后由于我们之前枚举了i和j的性质,那么当前以i为直径的一个端点,j为直径的另一个端点的圆必然只会不能包含一个点,并且将圆的边界强行拉到这个点后其他点编号小于j的点一定不会到圆的外面去。
啥意思?
最小圆覆盖学习_第2张图片
我们把圆的边界拉到(离当前直径最远的)k上是肯定合法的。
否则就会变成这样:
最小圆覆盖学习_第3张图片
并且此时k1、k2 但是由于我们之前已经枚举了i、j,那么凭啥(k1,k2)不能构成直径呢?
它构成直径后i、j就直接被包在圆里不用考虑了。
所以这个算法的正确性是有保证的。

你可能感兴趣的:(各类笔记)