poj 1696 Space Ant

大致题意:

一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,
能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.

卷包裹法:

形象思维假想一根无限长的绳子,一开始,左端粘在点集的最低点上。若有多个最低点,则去最做的最低点。然后拉动绳子的另一端逆时针绕行,每次紧贴一条边(这就是凸包上的一条边),这样绕行一周,绳子的形状就是凸包,这就是所谓的卷包裹法;该算法的效率比较低是O(n^2)的时间效率;

View Code
#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算法:用极坐标排序。

View Code
#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;
}

 

 

posted @ 2012-07-06 16:47  wutaoKeen  阅读(110)  评论(0编辑  收藏  举报