poj 1039 Pipe

来源:互联网 发布:球球大作战棒棒糖软件 编辑:程序博客网 时间:2024/04/30 18:53

题目链接:点击打开链接

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

40 12 24 16 460 12 -0.65 -4.457 -5.5712 -10.817 -16.550

Sample Output

4.67Through all the pipe.

题目大意:有一个管道,给出每个拐点的上壁的坐标,下壁的横坐标=上壁的横坐标,下壁的纵坐标=上壁的纵坐标-1,然后有一束光从入口射入,问最远能射多远(上下壁是不透明的),

ps:一开始自己读这个题的时候也知道让干什么了,但是考虑的是如何确定起点的位置,因为是double 型的无法枚举,然后就没做,过了几天看了一下题解,说枚举上下壁的拐点,与拐点的上下壁的连线看看有没有交点(即线段有没有交点,因为只是先判断,又给出了拐点的坐标,所以用叉积判断两个点是否在射线的一侧就行了,画图模拟一下),如果没有交点,也就是光碰壁了,但无法判断是上壁还是下壁,那就取最保险的都判断一下就可以了,找出与上壁或下壁的交点的最大x坐标,更新最大x坐标。求交点是直接用训练指南(p255)上的那个就行了  ,代码短还相对好理解,知识没有关于它的证明,看了一下他们写的求交点的算法,都考虑的好多,也没看懂怎么回事。下面是个很菜的代码,应该是最low的写法了吧。不过自己到是懂了。不懂可以模拟一下

<span style="font-size:18px;">#include <iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<cmath>#define eps 1e-3using namespace std;const double inf=99999.0;struct point{    double x;    double y;    point(double x=0,double y=0):x(x),y(y) { }}up[30],down[30];typedef point Vector;int max(int a,int b){    if(a>=b)return a;    return b;}Vector operator + (Vector A,Vector B){ return Vector (A.x+B.x,A.y+B.y);}Vector operator - (point A,point B){return Vector (A.x-B.x,A.y-B.y);}Vector operator *(Vector A,double p) {return Vector (A.x*p,A.y*p);}int dcmp(double x){    if(fabs(x)<eps)return 0;    else return x<0?-1:1;}double cross(Vector A,Vector B){    return A.x*B.y-A.y*B.x;}int judge(point a,point b,point c,point d){    return( dcmp(cross(c-a,b-a))*dcmp(cross(d-a,b-a))<=0);}double jiaodian(point P,Vector v,point Q,Vector w){    Vector u=P-Q;    double t=cross(w,u)/cross(v,w);    point h=P+v*t;   //cout<<h.x<<" "<<h.y<<endl;   return h.x;}int main(){    int n;    int i,j,k;    while(cin>>n,n)    {        for(i=1;i<=n;i++)        {            cin>>up[i].x>>up[i].y;            down[i].x=up[i].x;            down[i].y=up[i].y-1;        }        int all=0;        double mx=-inf;        for( i=1;i<=n;i++)        {            for( j=1;j<=n;j++)            {                if(i!=j)                {                    for( k=1;k<=n;k++)                    {                        if(!judge(up[i],down[j],up[k],down[k]))                        {                            break;                        }                    }                    if(k>n)                    {                        all=1;                        break;                    }                    else if(k>max(i,j))                    {                        double ans=jiaodian(up[i],down[j]-up[i],up[k],up[k]-up[k-1]);                        if(mx<ans)mx=ans;                        ans=jiaodian(up[i],down[j]-up[i],down[k],down[k]-down[k-1]);                        if(mx<ans)mx=ans;                    }                }            }            if(all)break;        }        if(all)printf("Through all the pipe.\n");        else  printf("%.2f\n",mx);    }    return 0;}</span>


0 0
原创粉丝点击