pku 1039 Pipe 叉积的应用

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

黑书上的一道题目:

题意:有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x0,y0),(x,y0-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道.
     如果一根光线自始至终都未擦到任何顶点,那么它肯定不是最优的,因为可以通过平移来使之优化,如果只碰到一个顶点,那也不是最优的,可以通过旋转,使它碰到另一个顶点,并且更优,即最优光线一定擦到一个上顶点和一个下顶点.
  这样枚举所有的上下两个转折点形成线段,然后从0到n枚举所有转折点如果与之相交则满足,直到找到不想交的然后计算x,找出最大的x即可。

#include <cstdio>

#include <cstring>

#include <iostream>

#define maxn 21

using namespace std;

const double eps = 1e-8;

struct point

{

    double x,y;

}up[maxn],down[maxn];

int n;

int dblcmp(double x)

{

    if (x > eps) return 1;

    else if (x < -eps) return -1;

    else return 0;

}

double det(double x1,double y1,double x2,double y2)

{

    return x1*y2 - x2*y1;

}

double cross(point a,point b,point c)

{

    return det(b.x - a.x,b.y - a.y,c.x - a.x,c.y - a.y);

}

double getx(point a,point b,point c,point d)

{

    double k1,k2,b1,b2;

    k1 = (b.y - a.y)/(b.x - a.x);

    k2 = (d.y - c.y)/(d.x - c.x);

    b1 = a.y - k1*a.x;

    b2 = d.y - k2*d.x;

    return (b2 - b1)/(k1 - k2);

}

void solve()

{

    int i,j,k;

    double ans = -10000000.0;

    for (i = 0; i < n; ++i)

    {

        for (j = 0; j < n; ++j)

        {

            if (i == j) continue;//同一个转折点上下就不用了

            //寻找不想交的

            for (k = 0; k < n; ++k)

            {

                if (dblcmp(cross(up[i],down[j],up[k]))*dblcmp(cross(up[i],down[j],down[k])) > 0)

                break;

            }

            double temp = 0;

            //计算x,并求出最大

            if (k < max(i,j)) continue;

            temp = getx(up[i],down[j],up[k],up[k - 1]);

            if (temp > ans) ans = temp;

            temp = getx(up[i],down[j],down[k],down[k - 1]);

            if (temp > ans) ans = temp;

            if (k >= n)

            {

                printf("Through all the pipe.\n");

                return ;

            }

        }

    }

    printf("%.2lf\n",ans);

}

int main()

{

    int i;

    while (~scanf("%d",&n))

    {

        if (!n) break;

        for (i = 0; i < n; ++i)

        {

            scanf("%lf%lf",&up[i].x,&up[i].y);

            down[i].x = up[i].x;

            down[i].y = up[i].y - 1.0;

        }

        solve();

    }

    return 0;

}

  

 

你可能感兴趣的:(pip)