//以下为原blog搬迁过来的内容
【题目大意】:给出n个水管的上接点(下接点的坐标为上接点的横坐标,和纵坐标减一),然后问你从管的左端射进一束光,在管里能够跑多远,输出到达最远点的横坐标。
【解题思路】:一开始觉得不好做,因为入口的点无法确定。后来,在纸上yy了几组数据,觉得好像是枚举一个管的上接点和下接点组成一个直线就可以了。上网搜了一下果然是这样,就开始动笔写了。我一开始是用叉积判的相交,但没有直接用叉积求交点。而是把枚举的两点化成一个直线方程来求交点,但是一直在wa,也不知道是怎么回事,后来换了叉积直接算就过了。现在我还是不知道为什么用直线方程求会错。discuss里面说精度1e-3都能过,感觉应该不是直线方程丢掉精度的原因吧。求大神指教
【代码】:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> #include <cmath> #include <string> #include <cctype> #include <map> #include <iomanip> using namespace std; #define eps 1e-11 #define pi acos(-1.0) #define inf 1<<30 #define pb push_back #define lc(x) (x << 1) #define rc(x) (x << 1 | 1) #define lowbit(x) (x & (-x)) #define ll long long #define INF 999999999.0 struct Point { double x,y; Point() {} Point(double a,double b) { x=a,y=b; } }pointu[1000],pointd[1000]; struct Line { Point a,b; Line() {} Line(Point x,Point y) { a=x,b=y; } }; double anss,p,q,ansx,ansy; int kk; inline int sig(double k) { return k < -eps ? -1 : k > eps; } inline double det(double x1, double y1, double x2, double y2) { return x1 * y2 - x2 * y1; } inline double xmult(Point o, Point a, Point b) { return det(a.x - o.x, a.y - o.y, b.x - o.x, b.y - o.y); } inline bool check(Line u, Line v) { double s1,s2; int d1,d2; d1=sig(s1=xmult(v.a, u.a, u.b)); d2=sig(s2=xmult(v.b, u.a, u.b)); if (d1*d2<0) { ansx=(v.a.x*s2-v.b.x*s1)/(s2-s1); ansy=(v.a.y*s2-v.b.y*s1)/(s2-s1); return true; } if (d1*d2==0) return true; //重合和端点相交也算相交 return false; } Point interect(const Point &x, const Point &y, double &a, double &b, double &c) { double u = fabs(a * x.x + b * x.y + c); double v = fabs(a * y.x + b * y.y + c); return Point((x.x * v + y.x * u) / (u + v), (x.y * v + y.y * u) / (u + v)); } void getline(const Point &x, const Point &y, double &a, double &b, double &c) { a = y.y - x.y; b = x.x - y.x; c = y.x * x.y - x.x * y.y; } int main() { int n; while (~scanf("%d",&n)) { if (n==0) break; anss=-1.0*INF; ansx=-1.0*INF; //横坐标记得清。 for (int i=0; i<n; i++) { scanf("%lf%lf",&p,&q); pointu[i]=Point(p,q); pointd[i]=Point(p,q-1); } for (int i=0; i<n; i++) { for (int j=0; j<n; j++) { Line tmp; tmp=Line(pointu[i],pointd[j]); kk=0; for (kk=0; kk<n; kk++) { Line tmp1; tmp1=Line(pointu[kk],pointd[kk]); if (check(tmp,tmp1)==false) break; } if (kk==n) anss=pointu[n-1].x; else if (kk>max(i,j)) { /*double a,b,c; getline(pointu[i],pointd[j],a,b,c); Point p; p=interect(pointu[kk-1],pointu[kk],a,b,c); if (p.x>anss) anss=p.x; p=interect(pointd[kk-1],pointd[kk],a,b,c); if (p.x>anss) anss=p.x;*/ Line tmp1; tmp1=Line(pointu[kk-1],pointu[kk]); if (check(tmp,tmp1)==true) if (ansx>anss) anss=ansx; tmp1=Line(pointd[kk-1],pointd[kk]); if (check(tmp,tmp1)==true) if (ansx>anss) anss=ansx; } } } if(anss==pointu[n-1].x) printf("Through all the pipe.\n"); else printf("%.2lf\n",anss); } return 0; }