题意:有一根管子,从管口射进去一根光线,问最远能到的点的横坐标。
枚举上下两个端点。先判断经过这两个端点的光线是否能和管口相交,再计算这根光线所能达到的最远的点。
要注意的地方:
1. 求的是横坐标,不是距离
2. 坐标可能会有负,ans初始化为-INF
3. 注意精度问题
卡精度WA了好久,好气啊……
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
const double eps=1e-8;
const int maxn=30;
const ll INF=0x3f3f3f3f3f;
struct Point{
double x,y;
Point(){}
Point(double a,double b){
x=a,y=b;
}
};
int n;
Point point_up[maxn],point_down[maxn];
Point interSectionPoint(Point p1,Point p2,Point p3,Point p4){
Point ret=p1;
double t=((p1.x-p3.x)*(p3.y-p4.y)-(p1.y-p3.y)*(p3.x-p4.x))
/((p1.x-p2.x)*(p3.y-p4.y)-(p1.y-p2.y)*(p3.x-p4.x));
ret.x+=(p2.x-p1.x)*t;
ret.y+=(p2.y-p1.y)*t;
return ret;
}
double dist(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(Point a,Point b){
return a.x<b.x;
}
int main(){
while (~scanf("%d",&n)&&n){
for (int i=1;i<=n;i++){
scanf("%lf %lf",&point_up[i].x,&point_up[i].y);
}
sort(point_up+1,point_up+n+1,cmp);
for (int i=1;i<=n;i++){
point_down[i].x=point_up[i].x;
point_down[i].y=point_up[i].y-1;
}
Point tmp;
double ans=-INF;
bool flag=false;
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (i==j)
continue;
Point left,right;
tmp=interSectionPoint(point_up[1],point_down[1],point_up[i],point_down[j]);
if (tmp.y+eps<point_down[1].y||tmp.y-eps>point_up[1].y)
continue;
left=tmp;
for (int k=2;k<=n;k++){
tmp=interSectionPoint(point_up[k],point_down[k],point_up[i],point_down[j]);
if (tmp.y+eps<point_down[k].y){
right=interSectionPoint(point_down[k],point_down[k-1],point_up[i],point_down[j]);
break;
}
else if (tmp.y-eps>point_up[k].y){
right=interSectionPoint(point_up[k],point_up[k-1],point_up[i],point_down[j]);
break;
}
else if (k==n){
flag=true;
}
}
ans=max(ans,right.x);
}
}
if (flag)
printf("Through all the pipe.\n");
else
printf("%.2f\n",ans);
}
}