poj 1696 Space Ant
大致题意:
一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,
能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.
卷包裹法:
形象思维假想一根无限长的绳子,一开始,左端粘在点集的最低点上。若有多个最低点,则去最做的最低点。然后拉动绳子的另一端逆时针绕行,每次紧贴一条边(这就是凸包上的一条边),这样绕行一周,绳子的形状就是凸包,这就是所谓的卷包裹法;该算法的效率比较低是O(n^2)的时间效率;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<cstring> #include<vector> using namespace std; class Point { public: int x,y; }point[54]; int on_segment( Point p, Point q1,Point q2 )//叉积 { return ( q1.x - p.x )*( q2.y - p.y ) - ( q2.x - p.x )*( q1.y - p.y ); } double Distance( Point a, Point b )//距离计算 { return sqrt( double(( a.x - b.x )*( a.x - b.x ) + ( a.y - b.y )*( a.y - b.y )) ); } bool segment( Point p, Point q1,Point q2 ) { int t = on_segment( p , q1 , q2 ); if( t < 0 ) return true; else if( t==0 && Distance( p , q1 ) > Distance( p , q2 )) return true; return false; } int main( ) { int N,n,num; while( scanf( "%d",&N )==1 ) { while( N -- ) { bool visit[54]={0};//标记已经进入凸包的点 int record[54],count=0;//记录点顺序 scanf( "%d",&n ); int min_y = 0x7fffffff,t=0; for( int i = 1; i <= n ; i++ ) { scanf( "%d %d %d",&num,&point[i].x , &point[i].y ); if( point[i].y < min_y )//寻找最低点 { min_y = point[i].y; t = i; } } record[++count] = t; visit[t] = true; while( count < n ) { int temp,s=record[count];//最新的凸包起点 for( int i = 1 ; i <= n ; i ++ )//寻找新的凸包起点 { if( !visit[i] ) { temp = i; break; } } for( int i = 1 ; i <= n ; i++ )//寻找最优的凸包起点 { if( !visit[i] && i != temp ) { if( segment( point[s],point[temp],point[i] ) ) { temp = i; } } } visit[temp] = true; record[++count] = temp; } printf( "%d",count ); for( int i = 1; i <= count ; i++ ) { printf( " %d",record[i] ); } puts( "" ); } } //system( "pause" ); return 0; }
下面用Graham—Scan算法:用极坐标排序。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<cstring> #include<vector> using namespace std; class Point { public: int x,y,num; }point[54]; int pos; double Distance( Point a, Point b ) { return sqrt( double(( a.x - b.x )*( a.x - b.x ) + ( a.y - b.y )*( a.y - b.y )) ); } int segment( Point p1 ,Point p2 ,Point q ) { return ( p1.x - q.x )*( p2.y - q.y ) - ( p2.x - q.x )*( p1.y - q.y ); } bool cmp( Point a, Point b ) { int t = segment( a , b, point[pos] ); if( t > 0 ) return true; else if( t==0 && Distance( a , point[pos] ) < Distance( b , point[pos] )) return true; return false; } int main( ) { int N,n,num; while( scanf( "%d",&N )==1 ) { while( N -- ) { scanf( "%d",&n ); for( int i = 0 ; i < n ; i ++ ) { scanf( "%d %d %d",&point[i].num , &point[i].x ,&point[i].y ); if( point[i].y < point[0].y ) swap( point[0],point[i] ); } printf( "%d %d",n ,point[0].num ); for( int i = 1 ; i < n ; i++ ) { pos = i - 1; sort( point + i , point + n ,cmp );//极坐标排序 printf( " %d",point[i].num ); } puts( "" ); } } //system( "pause" ); return 0; }