POJ1039
题解
- 我们把(xi,yi-1)--(xi,yi)作为一条垂直线段,那么一共有n条线段。
- 枚举任意两个点最为一条直线。从左开始枚举线段。
- 如果与每一条线段都能相交,那么就是全部穿越了。
- 如果与第一条线段不相交,那么这一条光线就不存在(无法在指定范围内发射)。
- 如果与第i条线段不相交,那么求直线与i,i-1上下两条线段的交点,求横坐标最大值。
代码:1A很舒服~
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
int const N = 20 + 10;
double const eps = 1e-8;
double const inf = 1e9;
int n;
double ans;
typedef struct Point{ //点和向量
double x,y;
Point(){};
Point(double x,double y):x(x),y(y){};
Point operator - (const Point& e)const{ //减
return Point(x - e.x,y - e.y);
}
Point operator + (const Point& e)const{ //减
return Point(x + e.x,y + e.y);
}
double operator ^ (const Point& e)const{ //叉乘
return x * e.y - y * e.x;
}
double operator * (const Point& e)const{ //点积
return x * e.x + y * e.y;
}
}Vector;
Point up[N],down[N];
struct Line{ //直线的定义
Point a,b;
Line(){};
Line(Point a,Point b):a(a),b(b){}
}l[N];
int dcmp(double x){ //判断符号
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
bool onsegment(Point p,Point a1,Point a2){
return dcmp((a1 - p) ^ (a2 - p)) == 0 && dcmp((a1 - p) * (a2 - p)) <= 0;
}
bool segment_intersection(Line line1,Line line2){ //判断直线和线段是否相交,line1表示直线,line2表示线段
double c1 = (line1.b - line1.a) ^ (line2.a - line1.a);
double c2 = (line1.b - line1.a) ^ (line2.b - line1.a);
if(dcmp(c1) * dcmp(c2) < 0) return true;
if(onsegment(line2.a,line1.a,line1.b) || onsegment(line2.b,line1.a,line1.b)) return true;
return false;
}
Point intersection(Point p,Vector v,Point q,Vector w){ //两直线(p+tv)和(q+tw)求交点
Vector u = p - q;
double t = (w ^ u) / (v ^ w);
return p + Point(v.x * t,v.y * t);
}
bool Judge(Line ll){
for(int i=1;i<=n;i++){
if(!segment_intersection(ll,l[i])){ //穿越不过求交点
if(i == 1) return false; //无法进入
Point p1 = intersection(ll.a,ll.b - ll.a,up[i],up[i] -up[i-1]);
Point p2 = intersection(ll.a,ll.b - ll.a,down[i],down[i] -down[i-1]);
ans = max(max(p1.x,p2.x),ans);
return false;
}
}
return true; //全部穿过
}
bool solve(){
for(int i=1;i<=n;i++){ //枚举第几列
for(int j=i+1;j<=n;j++){ //枚举上下端点
Line ll = Line(up[i],up[j]);
if(Judge(ll)) return true;
ll = Line(up[i],down[j]);
if(Judge(ll)) return true;
ll = Line(down[i],up[j]);
if(Judge(ll)) return true;
ll = Line(down[i],down[j]);
if(Judge(ll)) return true;
}
}
return false;
}
int main(){
while(~scanf("%d",&n) && n){
ans = -inf;
for(int i=1;i<=n;i++){
double x,y;
scanf("%lf%lf",&x,&y);
up[i] = Point(x,y);
down[i] = Point(x,y-1);
l[i] = Line(up[i],down[i]);
}
if(solve()) printf("Through all the pipe.\n");
else printf("%.2f\n",ans);
}
return 0;
}