poj 1039 Pipe

管道问题:

题意:有一宽度为1的折线管道,上面各顶点为(x0,y0),(x1,y1)...(xn,yn),下面各顶点为(x0,y0-1),(x1,y1-1),....(xn,yn-1),假设管道不透明,不反射,光线从左边入口(x0,y0),(x0,y0-1)之间射入,向四面八方传播,问光线最远能射到的X的坐标或者射穿整个管道。

这题用的是枚举法,枚举所有的上下点,要是最优,一定是一个上点与一个下点,这样才能使X最大;

每次枚举一个上下点,就判断是否与线段相交,我用的方法是与它左边由对应的上下点作线段相交(即与(xm,ym),(xm,ym-1)的连线),如果他们的叉乘大于0,则没有相交;

反则,相交,枚举它左边的所有线段,如果没有一个相交的则代表光线可以通过,那么我们就继续往下枚举;

View Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstdlib>
using namespace std;
class Point
{
public:
      double x ,y;    
}up[24],down[24];
class Line
{
public:
      double x1,y1,x2,y2;    
}L_up[24],L_down[24],L[24];
double Max( double a , double b )
{
    return a > b ? a : b;    
}
int Max( int a , int b )
{
    return a > b ? a : b;    
}
int dcmp( double x )
{
   if( fabs( x ) < 1.0e-8 ) return 0;
   if( x < 0 ) return -1;
   else return 1;    
}
void Get_line( int n )
{
   L[0].x1 = L[0].x2 = up[0].x;
   L[0].y1 = up[0].y ; L[0].y2 = down[0].y; 
   for( int i = 1 ; i < n ; i++ )
   {
      L[i].x1 = L[i].x2 = up[i].x;
      L[i].y1 = up[i].y ; L[i].y2 = down[i].y;
      L_up[i].x1 = up[i-1].x; L_up[i].x2 = up[i].x;
      L_up[i].y1 = up[i-1].y; L_up[i].y2 = up[i].y;
      L_down[i].x1=down[i-1].x;L_down[i].x2=down[i].x;
      L_down[i].y1=down[i-1].y;L_down[i].y2=down[i].y;
   }    
}
double on_segment( Point p1 , Point p2 , double x , double y )
{
    return ( p1.x - x )*( p2.y - y ) - ( p2.x - x )*( p1.y - y );    
}
int segment( Point p1 , Point p2 , Line line )
{
    int d1 = dcmp(on_segment( p1 , p2 , line.x1 , line.y1 ));
    int d2 = dcmp(on_segment( p1 , p2 , line.x2 , line.y2 ));
    return d1*d2;    
}
double Distance( double x1 , double y1 , double x2 , double y2 )
{
     return sqrt( ( x1 - x2 )*( x1 - x2 ) + ( y1 - y2 )*( y1 - y2 ) );    
}
double result( Point p1 , Point p2 , Line line )
{
    double x1,x2,y1,y2;
    double d1 = on_segment( p1 , p2 , line.x1 , line.y1 );
    double d2 = on_segment( p1 , p2 , line.x2 , line.y2 );
    y1 = (  d1 *line.x2 -  d2 *line.x1 )/(  d1  - d2);
    return y1;        
}
void Solve( int n )
{
  double ans,max = -1*0x7fffffff;
  bool flag = 1;
  for( int i = 0; i < n && flag; i++ )
  {
     for( int j=0; j < n && flag; j ++ )
     {
         int t = Max( i , j ),k;
         for(  k = 0 ; k < n && j!=i&& flag; k ++ )
         {
            if( segment( up[i],down[j],L[k] ) > 0 )
                break;        
         }        
         if( k == n ) flag = 0;
         else 
            if( k >= t )
            {
                if( segment( up[i],down[j],L_up[k] ) < 0 )
                {
                   max = Max(max , result( up[i],down[j],L_up[k] ));     
                }
                else if( segment( up[i],down[j],L_down[k] ) < 0 )
                {
                   max = Max(max , result( up[i],down[j],L_down[k] ));    
                }
                else if( segment( up[i],down[j],L_up[k] ) == 0 )
                {
                     max = Max(max , result( up[i],down[j],L_up[k] ));
                } 
                else if( segment( up[i],down[j],L_down[k] ) == 0 )
                       max = Max(max , result( up[i],down[j],L_down[k] ));    
            }        
     }    
  }    
  if( flag ) printf( "%.2f\n",max );
  else printf( "Through all the pipe.\n" );
}
int main(  )
{
   int n;
   while( scanf( "%d",&n ),n )
   {
      for( int i = 0 ; i < n ; i++ )
      {
          scanf( "%lf %lf",&up[i].x, &up[i].y );
          down[i].x = up[i].x;
          down[i].y = up[i].y-1;        
      }
      Get_line( n );
      Solve( n );        
   } 
   return 0;    
}

 

posted @ 2012-07-09 12:55  wutaoKeen  阅读(151)  评论(0编辑  收藏  举报