传送门:【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 ; }