poj 2187 Beauty Contest(凸包+旋转卡壳)
通过这题有学习了关于求凸多边形的直径的方法,真的很巧妙~
旋转卡壳可以用于求凸包的直径、宽度,两个不相交凸包间的最大距离和最小距离等,参考了下面的两个博客,原理基本上明白了。留下链接,以便后面复习用~
http://www.cnblogs.com/Booble/archive/2011/04/03/2004865.html
http://www.cppblog.com/staryjy/archive/2009/11/19/101412.html
其实这题完全可以不用旋转卡壳,可能是后台数据量很小,直接用暴力求解也可以过,而且时间和用了旋转卡壳的时间相差无几。
不用旋转卡壳(125ms)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #include <string> #define N 50005 using namespace std ; struct node { int x ; int y ; }p[N] , q[N] ; int n , top ; int dis ( struct node a , struct node b ) { return (( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y )); } double cross ( struct node p1 , struct node p2 , struct node p0 ) { return (( p1.x -p0.x ) * ( p2.y - p0.y ) - ( p2.x - p0.x ) * ( p1.y - p0.y )); } int cmp ( struct node p1 , struct node p2 ) { if ( cross ( p1 , p2 , p[0] ) > 0 ) return 1 ; if ( cross ( p1 , p2 , p[0] ) == 0 && dis( p1 , p[0] ) < dis( p2 , p[0] )) return 1 ; return 0 ; } void Graham () { int i , j , k ; k = 0 ; for ( i = 1 ; i < n ; i++ ) if ( (p[i].y < p[k].y ) || ( p[i].y == p[k].y && p[i].x < p[k].x )) k = i ; struct node tem = p[k] ; p[k] = p[0] ; p[0] = tem ; sort ( p , p + n , cmp ); top = 0 ; q[top++] = p[0] ; q[top++] = p[1] ; q[top++] = p[2] ; for ( i = 3 ; i < n ; i++ ) { while ( cross ( p[i] , q[top-1] , q[top-2] ) >= 0 ) top-- ; q[top++] = p[i] ; } } int main() { int i , j ; scanf ( "%d" , &n ) ; for ( i = 0 ; i < n ; i++ ) scanf ( "%d%d" , &p[i].x , &p[i].y ); if ( n == 2 ) { printf ( "%d\n" , ((p[0].x - p[1].x ) * ( p[0].x - p[1].x )) + ( p[0].y - p[1].y ) * ( p[0].y - p[1].y )) ; return 0 ; } Graham(); int maxx = 0 ; if ( top < 0 ) { maxx = dis ( p[0] , p[n-1] ); } else for ( i = 0 ; i < top ; i++ ) { for ( j = i + 1 ; j < top ; j++ ) { int len = dis( q[i] ,q[j] ); if ( len > maxx ) maxx = len ; } } printf ( "%d\n" , maxx ); return 0 ; }
用旋转卡壳(110ms)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <string> #define N 50005 using namespace std ; struct node { int x ; int y ; }p[N] , q[N] ; int n , top ; int dis ( struct node p1 , struct node p2 ) { return ( ( p1.x - p2.x ) * ( p1.x - p2.x ) + ( p1.y - p2.y ) * ( p1.y - p2.y )); } int cross ( struct node p1 , struct node p2 , struct node p0 ) { return ( ( p1.x - p0.x ) * ( p2.y - p0.y ) - ( p2.x - p0.x ) * ( p1.y - p0.y )); } int cmp ( struct node p1 , struct node p2 ) { if ( cross( p1 , p2 , p[0] ) > 0 ) return 1 ; if ( cross ( p1 , p2 , p[0] ) == 0 && dis( p1, p[0] ) < dis( p2 , p[0] )) return 1 ; return 0 ; } void Graham () { int i , j , k ; k = 0 ; for ( i = 1 ; i < n ; i++ ) if ( ( p[i].y < p[k].y ) || ( p[i].y == p[k].y && p[i].x < p[k].x )) k = i; struct node tem = p[k] ; p[k] = p[0] ; p[0] = tem ; sort ( p , p + n , cmp ); top = 0 ; q[top++] = p[0] ; q[top++] = p[1] ; q[top++] = p[2] ; for ( i = 3 ; i < n ; i++ ) { while ( cross ( p[i] , q[top-1] , q[top-2] ) >= 0 ) top-- ; q[top++] = p[i] ; } } int max (int a , int b) { return a > b ? a : b ; } int rotating_calipers() { int j = 1 , ans = 0 ; q[top] = q[0] ; for(int i = 0 ; i < top ; i++ ) { while(cross( q[i+1] , q[j+1] , q[i] ) > cross( q[i+1] , q[j] , q[i] )) j = ( j + 1 ) % top ; ans = max( ans , max( dis( q[i] , q[j] ) , dis( q[i+1] , q[j+1] ))); } return ans; } int main() { int i , d ; scanf ( "%d" , &n ) ; for ( i = 0 ; i < n ; i++ ) scanf ( "%d%d" , &p[i].x , &p[i].y ); if ( n == 2 ) { d = dis ( p[0] , p[1] ); printf ( "%d\n" , d ); return 0 ; } Graham(); if ( top < 0 ) { d = dis ( p[0] , p[n-1] ); } else { d = rotating_calipers(); } printf ( "%d\n" , d ); return 0 ; }