POJ 1039 Pipe

题意:给出n个坐标,然后对应y-1再生成n个坐标,构成一个管道,求从最左边路口射出的光能走多远。

题解:

首先,先明确一下思路:要求的最远能走多远,假设这个maxX=i;则在i的左边,肯定会经过两个顶点。为何?

因为如果 光能够走到i处,则中间不经过任何线段,则可以将它偏移,向上或者向下,最终会过两个点。

知道这一个之后,就可以枚举每两个点,然后判断维护一下就好了。

然后几个要注意的地方:

1.x可以是负数,所以max = - INF;

2.要判断交点i之前,这条线是否在管道内。

3.误差:假设我们过了顶点,就是输入的那些点,则远离顶点不超过1E-8,就算“擦过”,就是说,如果(1,1)(1,0)为顶点,则(1.0000000008456,1)光是可以穿过去的。

就是因为3WA了10多发。。汗!!

代码:

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <cmath>
  8 using namespace std;
  9 const double INF  = 1E200;
 10 const double eps = 1E-8;
 11 struct POINT{
 12         double x,y;
 13         POINT( double a = 0,double b = 0 )  { x = a; y = b; }
 14 };
 15 POINT pp[100+5],p[100+5];
 16 POINT tt[100+5],t[100+5];
 17 struct LINE           // 直线的解析方程 a*x+b*y+c=0  为统一表示,约定 a >= 0
 18 {
 19    double a;
 20    double b;
 21    double c;
 22    LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;}
 23 };
 24 struct LINESEG{
 25         POINT e;
 26         POINT s;
 27         LINESEG( POINT x,POINT y ) { e = x; s = y; }
 28         LINESEG(){}
 29 };
 30 LINESEG L1[100],L2[100];
 31 double multiply(POINT sp,POINT ep,POINT op)
 32 {
 33  return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));
 34 }
 35 LINE makeline( POINT p1,POINT p2 )
 36 {
 37         LINE tl;
 38         int sign = 1;
 39         tl.a = p2.y - p1.y;
 40         if(tl.a < eps)
 41         {
 42                 sign = -1;
 43                 tl.a = sign*tl.a;
 44         }
 45         tl.b = sign*( p1.x - p2.x );
 46         tl.c = sign*( p1.y*p2.x - p1.x*p2.y );
 47         return tl;
 48 }
 49 
 50 bool lineintersect(LINE l1,LINE l2,POINT &a) // 是 L1,L2
 51 {
 52  double d=l1.a*l2.b-l2.a*l1.b;
 53  if(abs(d)<eps) // 不相交
 54   return false;
 55  a.x = (l2.c*l1.b-l1.c*l2.b)/d;
 56  a.y = (l2.a*l1.c-l1.a*l2.c)/d;
 57  return true;
 58 }//
 59 bool online(LINESEG l,POINT pp)
 60 {
 61 
 62  return((fabs(multiply(l.e,pp,l.s))<=eps) &&( ( (pp.x-l.s.x)*(pp.x-l.e.x)<=eps )&&( (pp.y-l.s.y)*(pp.y-l.e.y)<=eps ) ) );
 63 }
 64 bool intersection( LINESEG l1,LINESEG l2,POINT &a  )
 65 {
 66         LINE ll1,ll2;
 67         ll1 = makeline(l1.s,l1.e);
 68         ll2 = makeline(l2.s,l2.e);
 69         if(lineintersect(ll1,ll2,a))
 70                 return online(l1,a);
 71         return false;
 72 }
 73 int main()
 74 {
 75         int n;
 76         while(cin>>n)
 77         {
 78                 if(!n) break;
 79                 LINESEG L;
 80                 for(int i = 1;i <= n; i++ )
 81                 { cin>>pp[i].x>>pp[i].y;
 82                   tt[i]=pp[i]; tt[i].y=pp[i].y-1;}
 83                 for(int i = 2;i <= n; i++ )
 84                 { L1[i-1].e=pp[i];L1[i-1].s=pp[i-1];
 85                   L2[i-1].e=tt[i];L2[i-1].s=tt[i-1]; }
 86                 double mx=-1*INF,my=-1*INF;
 87                 int flag = 0;
 88                 for(int i = 1;i <= n&&!flag; i++ )
 89                         for( int j = 1;j <= n&&!flag; j++)
 90                         {
 91                                 L.e = pp[i];
 92                                 L.s = tt[j];
 93                                 if(pp[i].x==tt[j].x)continue;
 94                                 double x1,x2,y1,y2;
 95                                 int flag1 = 0, flag2 = 0;
 96                                 for(int kk = 1;kk <= n-1;kk++ )
 97                                 {
 98                                         POINT a;
 99                                         if(intersection(L1[kk],L,a))
100                                         {
101                                                 double ttt = mx;
102                                                 x1 = a.x;
103                                                  if(x1>mx) mx=x1;
104                                                  double qqq = mx;
105                                                 //判断在mx之前是否出了管道,略丑
106                                                 LINE cc = makeline(L.s,L.e);
107                                                 for(int zz = 1;pp[zz].x<qqq&&zz<=n;zz++){
108                                                 double en = -cc.a*pp[zz].x/cc.b-cc.c/cc.b;
109                                                 double j1 = abs(pp[zz].y-en);
110                                                 double j2 = abs(en - pp[zz].y+1);
111                                                 double jj = j1+j2-1;
112 
113                                                 jj=abs(jj);
114                                                 if(jj<=eps);
115                                                 else mx=ttt;
116                                                 }
117                                         }
118                                 }
119                                 for(int kk = 1;kk <= n-1;kk++)
120                                 {
121                                         POINT a;
122                                         if(intersection(L2[kk],L,a))
123                                         {      flag2 = 1;
124                                                double ttt=mx;
125                                                x2 = a.x;
126                                                  if(x2>mx) mx=x2;
127                                                  double qqq = mx;
128                                                 LINE cc = makeline(L.s,L.e);
129 
130                                                 for(int zz = 1;pp[zz].x<qqq&&zz<=n;zz++){
131                                                 double en = -cc.a*pp[zz].x/cc.b-cc.c/cc.b;
132                                                 double j1 = abs(pp[zz].y-en);
133                                                 double j2 = abs(en - pp[zz].y+1);
134                                                 double jj = j1+j2-1;
135 
136                                                 jj=abs(jj);
137                                                 if(jj<=eps);else {mx=ttt;}
138                                                 }
139                                         }
140                                 }
141                                         double qqq = mx;
142                                         LINE cc = makeline(L.s,L.e);
143                                         for(int zz = 1;zz<=n;zz++){
144                                                 double en = -cc.a*pp[zz].x/cc.b-cc.c/cc.b;
145                                                 double j1 = abs(pp[zz].y-en);
146                                                 double j2 = abs(en - pp[zz].y+1);
147                                                 double jj = j1+j2-1;
148                                                 jj=abs(jj);
149                                                 if(jj<=eps);
150                                                 else
151                                                 {flag=2;
152                                                 }
153                                         }
154                                         if(flag==2) flag=0;
155                                         else{
156                                         flag = 1;break;
157                                         }
158                         }
159                 if(flag) puts("Through all the pipe.");
160                 else printf("%.2f\n",mx);
161         }
162 }        
View Code

 

posted on 2015-08-22 22:36  小松song  阅读(103)  评论(0)    收藏  举报

导航