poj 1113 Wall

题意:国王想建一个周长最短的城墙,使墙的任意一点到城墙的距离都 > L。求这面墙的周长。

我们知道在每个顶点的时候要计算弧度,其实我们知道每个都变形最后所有的弧形加起来会组成一个以L为半径的圆;这样周长就转换为凸包的周长+圆的周长;

这里我自己写了两种关于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;    

}point[1024];

int multi( Point p1 , Point p2 , Point q )

{

    return ( p1.x - q.x )*( p2.y - q.y ) - ( p2.x - q.x )*( p1.y - q.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 cmp( Point a, Point b )

{

   int t = multi( a , b , point[0]);

   if( t > 0 ) return true;

   else if( t == 0 && Distance( a , point[0] ) < Distance( b , point[0] ) )

            return true;

   return false;    

}

double Length( Point p[] , int len , int L )

{

    double dis = acos( -1.0 ) * L * 2;

    for(  int i = 1 ; i < len ; i ++)

    {

         dis += Distance( p[i-1] , p[i] );    

    }

    dis += Distance( p[0] , p[len-1] );    

    return dis;

}

int main(  )

{

    int N,L;

    while( scanf( "%d %d",&N,&L )==2 )

    {

      Point p[1024];

      int len = 0;

      for( int i = 0 ; i < N ; i ++ )

      {

          scanf( "%d %d",&point[i].x,&point[i].y );

          if( point[i].y < point[0].y )

             swap( point[i] , point[0] );

      }        

      sort( point + 1 , point + N , cmp );

      for( int i = 0 ; i < N ; i++ )

      {

          while( len >=2 && multi( p[len-1] , point[i] ,p[len-2] ) < 0 )

                 len--;

          p[len++] = point[i];        

      }

      printf( "%.0f\n",Length( p , len , L ) );    

    }

    //system( "pause" );

    return 0;

}

水平排序:

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[1024];

bool cmp( Point a , Point b )

{

      if( a.y == b.y )

          return a.x > b.x;

      return  a.y > b.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 )) );    

}

int segment( Point p2 , Point p1, Point q )

{

    return     ( p1.x - q.x )*( p2.y - q.y ) - ( p2.x - q.x )*( p1.y - q.y );

}

double Graham( int N ,int L)

{

       Point p[1024];

       int len = 0;

       for( int i = 0 ; i < N ; i ++ )

       {

        while( len >=2 && segment( point[i],p[len-1],p[len-2] )< 0 )

               len --;

        p[len++] = point[i];        

    };

    int t = len + 1;

    for( int i = N - 2; i >=0 ; i -- )

    {

        while( len >= t && segment( point[i],p[len-1],p[len-2] )< 0 )

               len --;

        p[len++] = point[i];

    }

    double dis = acos(-1.0) * L *2.0;

//    printf( "%lf\n",dis );

    for( int i = 1; i < len; i ++ )

    {

        dis += Distance( p[i-1] , p[i] );    

    }

    return dis;

}

int main(  )

{

    int N,L;

    while( scanf( "%d %d",&N, &L )==2 )

    {

       for( int i = 0 ; i < N; i ++ )

       {

            scanf( "%d %d",&point[i].x ,&point[i].y );        

       }    

       sort( point , point + N , cmp );

       printf( "%.0f\n",Graham( N ,L ));

    }

    //system( "pause" );

    return 0;

}

 

你可能感兴趣的:(poj)