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;
}

 

posted @ 2012-07-06 11:15  wutaoKeen  阅读(210)  评论(0编辑  收藏  举报