POJ 1039 Pipe(线段直线相交)

来源:互联网 发布:知网数据库 编辑:程序博客网 时间:2024/06/06 00:33

终于把这题过了。。。

体会到了计算几何的特点:姿势很重要。。。本来想按自己对叉积,线段相交的等等的理解来写,结果各种不知道为什么的 WA。后来换用 kuangbin 大神的模板,就过了。。

不过这题还是挺有意思的,是黑书上的题。

首先还是化“任意”问题为端点问题:考虑某一个最优解,如果它可以以某点为中心转动而得到另一个最优解,那么就转动它,如果不能转动,那么一定是因为它“卡”在某个管道的端点处了。即证明了一定存在经过端点的最优解,且一定是一个上端点,一个下端点(不然“卡”不住)。于是,枚举端点即可。

然后就是判断最左的交点。连接每一组上下端点,得到 k 条竖直的线段,考虑第一个不与直线相交的线段,则交点必在它之前的那条管道上。

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <queue>#include <map>#include <vector>#include <set>#include <string>#include <math.h>#include <cstdio>#include <cstring>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;}const int maxn = 25;int n;Point up[maxn],down[maxn];int main(){    while(scanf("%d", &n) && n) {        for(int 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;        }        double ans;        bool found = false, all;        for(int i = 0; i < n; i++) {            for(int j = 0; j < n; j++) {                if(i == j) continue;                Line l0(up[i],down[j]);                if(!Seg_inter_line(l0, Line(up[0], down[0])))                   continue;                all = true;                for(int k = 1; k < n; k++) {                    if(!Seg_inter_line(l0, Line(up[k],down[k]))) {                        all = false;                        double x1, x2;                        x1 = (l0 & Line(up[k-1], up[k])).second.x;                        x2 = (l0 & Line(down[k-1], down[k])).second.x;                        if(!found) {                            found = true;                            ans = max(x1, x2);                        } else                            ans = max(x2, (max(ans, x1)));                        break;                    }                }                if(all)                    goto result;            }        }        result:        if(all) puts("Through all the pipe.");        else printf("%.2lf\n", ans);    }    return 0;}


0 0
原创粉丝点击