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

【HDU】4946 Area of Mushroom 凸包

2017年10月16日 ⁄ 综合 ⁄ 共 1916字 ⁄ 字号 评论关闭

传送门:【HDU】4946 Area of Mushroom

题目分析:赤裸裸的凸包,因为速度最大的点一定比速度小的跑的快,所以一段时间以后速度大的点一定能比速度小的点先到远处,所以如果可能有无限面积的优先考虑速度最大的。然后,如果多个人速度最大,那么被包围在其他速度大的人里面的面积一样不会是无限的,所以只要对速度大的人求一次凸包即可。并且如果速度最大的人速度为零,则所有人的面积都不是无限的。

这次失策,在求凸包的时候考虑到重复点的问题,但是没有去掉,导致一直wa,最后弃疗去重交了一发竟然AC。。仔细想想也是,如果有两个点在同一位置,那么排在这两个点之后的点和这两个点形成的叉积一定等于0(因凸包为一条边上有多个点则这多个点的面积都应该是无限的,所以当叉积为0的时候我们也算这个点暂时属于凸包),那么最后算法很可能得到一个“凹包”。。。

代码如下:

#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 = 2333 ;

struct Point {
	int x , y ;
	int idx , v ;
	bool flag ;
	Point ( int x = 0 , int y = 0 ) : x ( x ) , y ( y ) {}
	Point operator - ( const Point &b ) const {
		return Point ( x - b.x , y - b.y ) ;
	}
	void input ( int &_idx ) {
		scanf ( "%d%d%d" , &x , &y , &v ) ;
		idx = _idx ;
		flag = 0 ;
	}
} p[MAXN] ;

bool res[MAXN] ;
int S[MAXN] , top ;
int n ;

int Cross ( const Point &A , const Point &B ) {
	return A.x * B.y - A.y * B.x ;
}

int cmp1 ( const Point &a , const Point &b ) {
	if( a.x != b.x ) return a.x < b.x ;
	else if ( a.y != b.y ) return a.y < b.y ;
	else return a.v > b.v ;
}

int cmp2 ( const Point &a , const Point &b ) {
	return a.v > b.v ;
}

int ConvexHull ( Point* p , int n ) {
	top = 0 ;
	sort ( p , p + n , cmp1 ) ;
	REP ( i , 0 , n - 1 )
		if ( p[i].x == p[i + 1].x && p[i].y == p[i + 1].y && p[i].v == p[i + 1].v )
			p[i].flag = 1 ;
	REP ( i , 0 , n ) {
		if ( p[i].flag ) continue ;
		while ( top > 1 && Cross ( p[S[top - 1]] - p[S[top - 2]] , p[i] - p[S[top - 2]] ) < 0 ) -- top ;
		S[top ++] = i ;
	}
	int k = top ;
	REV ( i , n - 2 , 0 ) {
		if ( p[i].flag ) continue ;
		while ( top > k && Cross ( p[S[top - 1]] - p[S[top - 2]] , p[i] - p[S[top - 2]] ) < 0 ) -- top ;
		S[top ++] = i ;
	}
	if ( n > 1 ) -- top ;
	return top ;
}

void solve () {
	CLR ( res , 0 ) ;
	REP ( i , 0 , n ) p[i].input ( i ) ;
	sort ( p , p + n , cmp2 ) ;
	if ( !p[0].v ) {
		REP ( i , 0 , n ) printf ( "0" ) ;
		printf ( "\n" ) ;
		return ;
	}
	int m ;
	for ( m = 0 ; m < n - 1 ; ++ m ) if ( p[m].v != p[m + 1].v ) break ;
	m = ConvexHull ( p , m + 1 ) ;
	REP ( i , 0 , m ) res[p[S[i]].idx] = 1 ;
	sort ( p , p + n , cmp1 ) ;
	REP ( i , 0 , n - 1 )
		if ( p[i].x == p[i + 1].x && p[i].y == p[i + 1].y && p[i].v == p[i + 1].v )
			res[p[i].idx] = res[p[i + 1].idx] = 0 ;
	REP ( i , 0 , n ) printf ( "%d" , res[i] ) ;
	printf ( "\n" ) ;
}

int main () {
	int cas = 0 ;
	while ( ~scanf ( "%d" , &n ) && n ) {
		printf ( "Case #%d: ", ++ cas ) ;
		solve () ;
	}
	return 0 ;
}

抱歉!评论已关闭.