现在的位置: 首页 > 综合 > 正文

【UVALive】6168 Fat Ninjas 并查集

2017年10月15日 ⁄ 综合 ⁄ 共 1111字 ⁄ 字号 评论关闭

传送门:【UVALive】6168 Fat Ninjas

题目分析:二分+并查集判断正方形的下边界是否和上边界相连,不相连则这次得到的是一个可行解,继续调整下界,否则调整上界。

代码如下:

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

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 5005 ;
double eps = 1e-5 ;

double d[MAXN][MAXN] ;
int p[MAXN] ;
int rank[MAXN] ;
int X[MAXN] , Y[MAXN] ;
int n , L ;

int find ( int x ) {
	return p[x] == -1 ? x : ( p[x] = find ( p[x] ) ) ;
}

void Union ( int x , int y ) {
	x = find ( x ) ;
	y = find ( y ) ;
	if ( x != y ) {
		if ( rank[x] <= rank[y] ) {
			p[x] = y ;
			if ( rank[x] == rank[y] )
				++ rank[y] ;
		}
		else
			p[y] = x ;
	}
}

double dist ( int i , int j ) {
	double x = X[i] - X[j] ;
	double y = Y[i] - Y[j] ;
	return sqrt ( x * x + y * y ) ;
}

int check ( double D ) {
	CLR ( rank , 0 ) ;
	CLR ( p , -1 ) ;
	REP ( i , 0 , L ) {
		if ( Y[i] + D >= n )
			Union ( i , L ) ;
		if ( Y[i] - D <= 0 )
			Union ( i , L + 1 ) ;
		REP ( j , i + 1 , L )
			if ( d[i][j] <= D )
				Union ( i , j ) ;
	}
	if ( find ( L ) == find ( L + 1 ) )
		return 0 ;
	return 1 ;
}

void solve () {
	REP ( i , 0 , L )
		scanf ( "%d%d" , &X[i] , &Y[i] ) ;
	REP ( i , 0 , L )
		REP ( j , i + 1 , L )
			d[i][j] = d[j][i] = dist ( i , j ) ;
	double l = 0 , r = MAXN ;
	while ( r - l > eps ) {
		double mid = ( l + r ) / 2 ;
		if ( check ( mid ) )
			l = mid ;
		else
			r = mid ;
	}
	printf ( "%.3f\n" , l ) ;
}

int main () {
	while ( ~scanf ( "%d%d" , &n , &L ) && ( n || L ) )
		solve () ;
	return 0 ;
}

抱歉!评论已关闭.