poj 1039 Pipe (判断 直线和 线段 是否相交 并 求交点)

http://poj.org/problem?id=1039 

 

 

题意:已知电缆是由一段段直的管道连接而成的,并知道这些管道的位置,问一束光从最左边射进来,你可以调节光入射的位置和角度,问最远能射到多远。(光束不能射穿管道)

 

poj <wbr>1039 <wbr>:Pipe <wbr>(几何)

题解:

枚举 :  一个最优的 直线  可能 和 管道没有交点,(但是 我们可以经过 平移,旋转 使其 与 管道 有 交点 这样的解 同样是最优 的,我们 枚举和 管道 有两个擦点的直线 (这样 才能 做这道题))

枚举上下两个顶点成光线所在直线,然后判断光线是否能合法,合法的话求出它射到的最远距离。
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include< set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include< string>
 11  #define Min(a,b) a<b?a:b
 12  #define Max(a,b) a>b?a:b
 13  #define CL(a,num) memset(a,num,sizeof(a));
 14  #define maxn  40
 15  #define eps  1e-8
 16  #define inf 100000000
 17  #define mx 1<<60
 18  #define ll   __int64
 19  using  namespace std;
 20 
 21  struct point
 22 {
 23      double x;
 24      double y;
 25 }up[maxn],dp[maxn];
 26  double ans ;
 27  int  n ;
 28  int dbcmp( double x)
 29 {
 30      if(fabs(x) < eps)  return  0;
 31      if(x<  0return - 1;
 32      else   return  1 ;
 33 
 34 }
 35  double det( double x1, double y1, double x2, double y2)
 36 {
 37      return x1*y2 - x2*y1 ;
 38 }
 39  double cross(point a,point b,point c)
 40 {
 41      return det(b.x - a.x,b.y - a.y,c.x - a.x,c.y - a.y);
 42 }
 43  double getx(point a,point b,point c,point d) //   a,b 代表直线 ,c,d 代表 线段
 44  {
 45      double s1 = cross(a,b,c);
 46      double s2 = cross(a,b,d);
 47 
 48      return (c.x*s2 - d.x*s1)/(s2 - s1) ; //  求 交点 的 x 坐标
 49  }
 50  bool  solve( )
 51 {
 52 
 53      int i, j,k;
 54 
 55     for(i =  0 ; i< n;i++)
 56    {
 57        for(j =  0 ; j< n;j++)
 58       {
 59            if(i == j) continue ;
 60            for(k =  0 ; k < n;k++)
 61           {
 62                if(dbcmp(cross(up[i],dp[j],up[k])) * dbcmp(cross(up[i],dp[j],dp[k])) > 0)
 63                 break;
 64           }
 65 
 66            if(k == n)
 67           {
 68 
 69                return   true;
 70           }
 71 
 72            if(k < max(i,j))  continue ; //  判断 是否合法
 73             else
 74           {
 75                double  tmp = getx(up[i],dp[j],up[k],up[k -  1]);
 76                if(tmp > ans) ans = tmp;
 77               tmp = getx(up[i],dp[j],dp[k],dp[k -  1]);
 78                if(tmp >ans) ans = tmp ;
 79           }
 80 
 81       }
 82    }
 83 
 84 
 85 
 86     return  false ;
 87 
 88 
 89 
 90 }
 91 
 92  int main()
 93 {
 94      int i,j;
 95      // freopen("data.txt","r",stdin);
 96       while(scanf( " %d ",&n),n)
 97     {
 98          for(i =  0 ; i < n;i++)
 99         {
100             scanf( " %lf%lf ",&up[i].x,&up[i].y);
101             dp[i].x = up[i].x;
102             dp[i].y = up[i].y -  1;
103         }
104 
105          ans = -inf;
106          bool flag =  false ;
107          if(n <  3) flag =  true ;
108           if(!flag)flag = solve();
109 
110          if(flag) printf( " Through all the pipe.\n ");
111          else printf( " %.2lf\n ",ans) ;
112 
113     }
114 }

 


转载于:https://www.cnblogs.com/acSzz/archive/2012/08/26/2657539.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值