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