1. 程式人生 > >POJ - 1039 Pipe(計算幾何)

POJ - 1039 Pipe(計算幾何)

std algo double 透明 pac down queue == 是否

http://poj.org/problem?id=1039

題意

有一寬度為1的折線管道,上面頂點為(xi,yi),所對應的下面頂點為(xi,yi-1),假設管道都是不透明的,不反射的,光線從左邊入口處的(x1,y1),(x1,y1-1)之間射入,向四面八方傳播,求解光線最遠能傳播到哪裏(取x坐標)或者是否能穿透整個管道。

分析

最遠的直線必定經過一個上折點和一個下折點。枚舉這兩個點即可。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include 
<queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; const double eps = 1e-8; int sgn(double x) { if(fabs(x) < eps)return 0; if(x < 0)return -1; else return 1; } struct Point {
double x,y; Point(){} Point(double _x,double _y) { x = _x;y = _y; } Point operator -(const Point &b)const { return Point(x - b.x,y - b.y); } //叉積 double operator ^(const Point &b)const { return x*b.y - y*b.x; }
//點積 double operator *(const Point &b)const { return x*b.x + y*b.y; } void input() { scanf("%lf%lf",&x,&y); } }; struct Line { Point s,e; Line(){} Line(Point _s,Point _e) { s = _s;e = _e; } //兩直線相交求交點 //第一個值為0表示直線重合,為1表示平行,為0表示相交,為2是相交 //只有第一個值為2時,交點才有意義 pair<int,Point> operator &(const Line &b)const { Point res = s; if(sgn((s-e)^(b.s-b.e)) == 0) { if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);//重合 else return make_pair(1,res);//平行 } double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x += (e.x-s.x)*t; res.y += (e.y-s.y)*t; return make_pair(2,res); } }; //判斷直線和線段相交 bool Seg_inter_line(Line l1,Line l2) //判斷直線l1和線段l2是否相交 { return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0; } Point up[100],down[100]; int main() { int n; while(scanf("%d",&n) == 1 && n) { for(int i = 0;i < n;i++) { up[i].input(); down[i] = up[i]; down[i].y -= 1; } bool flag = false;//穿過所有的標記 double ans = -10000000.0; int k; for(int i = 0;i < n;i++) { for(int j = 0;j < n;j++) { for(k = 0;k < n;k++) //直線L最大延伸到第k-1節管子 if(Seg_inter_line(Line(up[i],down[j]),Line(up[k],down[k])) == false) break; if(k >= n) { flag = true; break; } if(k > max(i,j)) //由於不清楚L究竟是與第k-1節管子的上管壁還是下管壁相交,因此都計算交點,取最優 { if(Seg_inter_line(Line(up[i],down[j]),Line(up[k-1],up[k]))) { pair<int,Point>pr = Line(up[i],down[j])&Line(up[k-1],up[k]); Point p = pr.second; ans = max(ans,p.x); } if(Seg_inter_line(Line(up[i],down[j]),Line(down[k-1],down[k]))) { pair<int,Point>pr = Line(up[i],down[j])&Line(down[k-1],down[k]); Point p = pr.second; ans = max(ans,p.x); } } } if(flag)break; } if(flag)printf("Through all the pipe.\n"); else printf("%.2lf\n",ans); } return 0; }

POJ - 1039 Pipe(計算幾何)