//以下为原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;
}