poj 1556 The Doors

这是一道简单而有趣的几何题。如果将每扇门的上下起点,加上起点与终点作为无向图的顶点,两个相互之间可以直达(即连线不经过任何障碍)的顶点之间连一条边,长度作为两点之间的距离,这样就可以转化为图论的最短路问题;

View Code
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<set>

#include<cstring>

#include<vector>

using namespace std;

class Line

{

public:

     double x,y1,y2;    

}line[50];

class Point

{

public:    

    double x,y;

}point[100];

double map[124][124];

bool cmp_point( Point a, Point b )

{

     if( a.x == b.x ) return a.y > b.y;

     return a.x < b.x;    

}

bool cmp_line( Line a,Line b )

{

       return a.x < b.x;

}

double judge( Point p1 , Point p2, Point q  )//叉积 

{

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

}

bool Segment( Point p , Point  q, Point a , Point b )//判断线段是否相交 

{

     double d1 = judge( p , q, a );

     double d2 = judge( p , q ,b );

     double d3 = judge( a , b ,p );

     double d4 = judge( a , b ,q );

     if( d1*d2 < 0 && d3 * d4 < 0 ) return true;//如果叉积相乘都小于零,则线段相交 

     else return false;     

}

double Distance( Point a, Point b )//计算距离 

{

    return sqrt(( a.x - b.x )*( a.x - b.x ) + ( a.y - b.y )*( a.y - b.y ));    

}

void Get_map( int N,int M )//构图 

{

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

    {

       for( int j = i + 1 ; j < N ; j++ )

       {

           bool flag = 1;

           for( int k = 0 ; k < M && flag ; k+=2 )

           {

              int t = 0,F[2]={0};

              while( point[i].x < line[k].x && point[j].x > line[k].x && t < 2 )

              {//如果两点的线段与门相交代表可以穿过,

             

                  Point a,b; a.x =  b.x = line[k+t].x ;

                  a.y = line[k+t].y1 ; b.y = line[k+t].y2;

                  F[t]= Segment( point[i],point[j],a ,b ); 

                  t++;    

              }     

              //注意:同一堵墙有两扇门,同一赌墙只要有一个相交就可以了 

              if( t > 0 ) flag = F[0]|F[1];    

            }

           if( flag ) map[i][j] = Distance( point[i] , point[j] );    

       }    

    }    

}

double Dij( int N )//求最短路 

{

   double dis[100];

   bool hash[100];

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

   {

       hash[i] = false ; dis[i] = 100000000;        

   }

   dis[0] = 0;

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

   {

      double min = 100000000;

      int t;

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

      {

           if( !hash[j] && min > dis[j] )

           {

              min = dis[j] ; t = j;        

           }        

      }

      if( t==N-1 ) return dis[N-1];

      hash[t] = true;

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

      {

          if( !hash[j] && map[t][j] !=100000000 && dis[j] > dis[t] + map[t][j] )

               dis[j] = dis[t] + map[t][j];        

      } 

   }

   return dis[N-1];

}

void empty( int N )

{

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

    {

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

        {

            map[i][j] = 100000000;

        }    

    }    

}

int main(  )

{

    int n;

    double x,y[4];

    while( scanf( "%d",&n ),n!=-1 )

    {

        int count_point = 0 , count_line = 0;

        point[count_point].x = 0; point[count_point++].y = 5;

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

        {

            scanf( "%lf",&x );

            for( int j = 0 ; j < 4 ; j ++ )

            {

               scanf( "%lf",&y[j] );

               point[count_point].x = x;

               point[count_point++].y = y[j];    

               if( j % 2 )

               {

                  line[count_line].x = x;

                  line[count_line].y1 = y[j-1];

                  line[count_line++].y2 = y[j];        

               }

            }

        }

        

        point[count_point].x = 10; point[count_point++].y = 5;

        sort( point , point + count_point , cmp_point );

        sort( line , line + count_line, cmp_line );

        empty( count_point );

        Get_map( count_point, count_line );

        printf( "%.2f\n",Dij( count_point ));    

    }

    //system( "pause" );

    return 0;

}

 

你可能感兴趣的:(poj)