POJ 1039--Pipe

来源:互联网 发布:上海耀姚贸易 知乎 编辑:程序博客网 时间:2024/04/30 20:16

计算几何题目:题目给出一些弯管,问最后从入口发射的光线能到达的最右端。

参考《算法艺术与信息学竞赛》p359,最优的发射光线只能是某个拐点上端点和某个拐点下端点的连线。

根据以上原理,我们从左往右判断光线是否能通过拐点连接的纵墙,若能通过所有则输出Through all the pipe.

若首先交于某墙壁,求出交点,保存最大值输出。


#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define maxN 22struct point{    float x,y;};point up[maxN];point down[maxN];float direction(point p1,point p2,point p3)         //差积{    return (p3.x-p1.x)*(p2.y-p1.y)-(p3.y-p1.y)*(p2.x-p1.x);}bool IsCrossBentWall(point upNode,point downNode,point wallUp, point wallDown)   //检查光线是否能跨越横坐标为墙壁{    float d1 = direction(upNode,downNode,wallUp);    float d2 = direction(upNode,downNode,wallDown);    if(d1*d2 <= 0)      //墙壁端点在光线两端或者端点在光线上        return true;    else        return false;}float intersection(point p1,point p2,point p3,point p4)     //两条直线交点{    float k1 = (p2.y-p1.y)/(p2.x-p1.x);    float k2 = (p4.y-p3.y)/(p4.x-p3.x);    float dis =  (p3.y-k2*p3.x-p1.y+k1*p1.x)/(k1-k2);    return dis;}float calcDis(int upNo,int downNo,int wallNo){    float x1 = -1e6;    float x2 = -1e6;    if(IsCrossBentWall(up[upNo],down[downNo],up[wallNo-1],up[wallNo]))  //上壁        x1 =  intersection(up[upNo],down[downNo],up[wallNo-1],up[wallNo]);    if(IsCrossBentWall(up[upNo],down[downNo],down[wallNo-1],down[wallNo]))  //下壁        x2 = intersection(up[upNo],down[downNo],down[wallNo-1],down[wallNo]);    return x1>x2?x1:x2;             //选出与上下壁想交点的较大x}int main(){    int i,j,k;    int N;    char IsThroughAll;    float maxDis,tmpDis;    while(~scanf("%d",&N)&&N)    {        maxDis = -1e6;        for(i = 0;i < N;i++)        {            scanf("%f%f",&up[i].x,&up[i].y);            down[i].x = up[i].x;            down[i].y = up[i].y-1;        }        for(i = 0;i < N;i++)        {            for(j = 0;j < N;j++)            {                IsThroughAll = false;                if(i != j)                {                    for(k = 0;k < N;k++)                    {                        if(k != i&&k != j&&!IsCrossBentWall(up[i],down[j],up[k],down[k]))                            break;                    }                    if(k == N)    //从前往后能通过最后一个纵墙                    {                        IsThroughAll = true;                        break;                    }                    if(k > j)      //最后通过的墙壁在光线下端点的右边                    {                        tmpDis = calcDis(i,j,k);                        if(maxDis < tmpDis)                            maxDis = tmpDis;                    }                }            }            if(IsThroughAll)                break;        }        if(IsThroughAll)        {            printf("Through all the pipe.\n");            continue;        }        printf("%.2f\n",maxDis);    }    return 0;}


0 0
原创粉丝点击