Pipe Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 8280 Accepted: 2483
Description
The GX Light Pipeline Company started to prepare bent pipes for the new transgalactic light pipeline. During the design phase of the new pipe shape the company ran into the problem of determining how far the light can reach inside each component of the pipe. Note that the material which the pipe is made from is not transparent and not light reflecting. Each pipe component consists of many straight pipes connected tightly together. For the programming purposes, the company developed the description of each component as a sequence of points [x1; y1], [x2; y2], . . ., [xn; yn], where x1 < x2 < . . . xn . These are the upper points of the pipe contour. The bottom points of the pipe contour consist of points with y-coordinate decreased by 1. To each upper point [xi; yi] there is a corresponding bottom point [xi; (yi)-1] (see picture above). The company wants to find, for each pipe component, the point with maximal x-coordinate that the light will reach. The light is emitted by a segment source with endpoints [x1; (y1)-1] and [x1; y1] (endpoints are emitting light too). Assume that the light is not bent at the pipe bent points and the bent points do not stop the light beam.Input
The input file contains several blocks each describing one pipe component. Each block starts with the number of bent points 2 <= n <= 20 on separate line. Each of the next n lines contains a pair of real values xi, yi separated by space. The last block is denoted with n = 0.Output
The output file contains lines corresponding to blocks in input file. To each block in the input file there is one line in the output file. Each such line contains either a real value, written with precision of two decimal places, or the message Through all the pipe.. The real value is the desired maximal x-coordinate of the point where the light can reach from the source for corresponding pipe component. If this value equals to xn, then the message Through all the pipe. will appear in the output file.Sample Input
4 0 1 2 2 4 1 6 4 6 0 1 2 -0.6 5 -4.45 7 -5.57 12 -10.8 17 -16.55 0Sample Output
4.67 Through all the pipe.Source
Central Europe 1995题意大致为:
有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x1,y1),(x1,y1-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道.
分析如下:上下顶点对于限制光线十分重要。首先:我们知道如果一条光线始终没有接触到一个顶点,那么它肯定不是最优的,可以通过平移使之接触到一个顶点,且更优化。其次,又可以推知,如果一条光线只接触到一个顶点,那么其也必定不是最优的,可以通过旋转使之接触两个顶点。且更优化。且这两个顶点必定是一个上顶点和一个下顶点。
分析到这里,思路就很明确了。 枚举任意上顶点和下顶点,构成一条直线。若该直线在x等于x0的情况下y值在down与up之间,则说明是一条”正确“的直线。那么接下来就是判断每段管道的上下层是否与该直线相交,直到规范相交为止,然后求出交点横坐标。最后求出每条正确直线的交点横坐标的最大值,即为题意要求的值。
代码:代码转自kuangbin巨巨 #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 = i+1;j < n;j++) { for(k = 0;k < n;k++) 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)) { 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); } } for(k = 0;k < n;k++) if(Seg_inter_line(Line(down[i],up[j]),Line(up[k],down[k])) == false) break; if(k >= n) { flag = true; break; } if(k > max(i,j)) { if(Seg_inter_line(Line(down[i],up[j]),Line(up[k-1],up[k]))) { pair<int,Point>pr = Line(down[i],up[j])&Line(up[k-1],up[k]); Point p = pr.second; ans = max(ans,p.x); } if(Seg_inter_line(Line(down[i],up[j]),Line(down[k-1],down[k]))) { pair<int,Point>pr = Line(down[i],up[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; }