• POJ 1556 E


    题意:给定n堵墙,现在要你从(0,5)走去(10,5)的最短距离

    思路:刚开始还想模拟,就是从(0,5)走,每次x向右一格,然后判断有没和线段相交就可以。但是它的们有可能是小数形式给出的,这样就GG了(x--x+1中可能存在很多门)。正确的方法应该是建图,对于所有门,他们都有端点的,先把他们加入到图中,包括起点的话,一共有num个点吧。然后暴力判断e[i][j]是否能到达就可以,这里用线段相交就可以判断。然后floyd一下就好。bug点:门的端点不应该加进来,就是(x,0)、(x,10)这样的点不应该加入图中,因为那个是死角,不能出去了。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const double eps = 1e-8;
    const int maxn = 100+20;
    bool same (double a,double b)
    {
        return fabs(a-b)<eps;
    }
    struct coor
    {
        double x,y;
        coor(){}
        coor(double xx,double yy):x(xx),y(yy){}
        double operator ^(coor rhs) const //计算叉积(向量积)
        {
            return x*rhs.y - y*rhs.x;
        }
        coor operator -(coor rhs) const //坐标相减,a-b得到向量ba
        {
            return coor(x-rhs.x,y-rhs.y);
        }
        double operator *(coor rhs) const //数量积
        {
            return x*rhs.x + y*rhs.y;
        }
        bool operator ==(coor rhs) const
        {
            return same(x,rhs.x)&&(y,rhs.y);//same的定义其实就是和eps比较
        }
    }a[maxn];
    
    struct Line
    {
        coor point1,point2;
        Line(){}
        Line(coor xx,coor yy):point1(xx),point2(yy){}
        bool operator &(Line rhs) const //判断直线和rhs线段是否相交
        {
            //自己表示一条直线,然而rhs表示的是线段
            //思路,判断rhs线段上两个端点是否在this直线的同一侧即可,用一侧,就不相交
            coor ff1 = point2 - point1; //直线的方向向量
            return ( ((rhs.point1-point1)^ff1) * ((rhs.point2-point1)^ff1) ) <= 0;//符号不同或者有0,证明相交
        }
    }LINE[maxn];
    
    
    bool OnSegment (coor a,coor b,coor c) //判断点C是否在线段ab上
    {
        double min_x = min(a.x,b.x), min_y = min(a.y,b.y);
        double max_x = max(a.x,b.x), max_y = max(a.y,b.y);
        if (c.x>=min_x && c.x<=max_x && c.y>=min_y && c.y<=max_y) return true;
        else return false;
    }
    bool SegmentIntersect (coor a,coor b,coor c,coor d)
    {
        double d1 = (b-a)^(d-a); //direction(a,b,d);以a为起点,计算ab和ab的叉积
        double d2 = (b-a)^(c-a);
        double d3 = (d-c)^(a-c);
        double d4 = (d-c)^(b-c);
        if (d1*d2<0 && d3*d4<0) return true;
        else if (d1 == 0 && OnSegment(a,b,d)) return true;
        else if (d2 == 0 && OnSegment(a,b,c)) return true;
        else if (d3 == 0 && OnSegment(c,d,a)) return true;
        else if (d4 == 0 && OnSegment(c,d,b)) return true;
        else return false;
    }
    
    int n;
    int all=0;
    double dis (coor a,coor b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    double e[maxn][maxn];
    void work ()
    {
        all = 0;
        int num=0;
        for (int i=1;i<=n;++i)
        {
            double aa,bb,cc,dd,ee;
            scanf("%lf%lf%lf%lf%lf",&aa,&bb,&cc,&dd,&ee);
            ++all;
            LINE[all].point1 = coor(aa,0); //a[++num]=coor(aa,0);
            LINE[all].point2 = coor(aa,bb);a[++num]=coor(aa,bb);
    
            ++all;
            LINE[all].point1 = coor(aa,cc);a[++num]=coor(aa,cc);
            LINE[all].point2 = coor(aa,dd);a[++num]=coor(aa,dd);
    
            ++all;
            LINE[all].point1 = coor(aa,ee);a[++num]=coor(aa,ee);
            LINE[all].point2 = coor(aa,10);//a[++num]=coor(aa,10);
        }
        a[++num]=coor(0,5);
        a[++num]=coor(10,5);
        //memset(e,0x3f,sizeof e);
        for (int i=1;i<=maxn-20;++i)
        {
            for (int j=1;j<=maxn-20;++j)
            {
                e[i][j]=100000000.0;
            }
    
        }
        for (int i=1;i<=num;++i)
        {
            for (int j=i+1;j<=num;++j)
            {
                int k;
                //if (same(a[j].y,0)||same(a[j].y,10)||same(a[i].y,0)||same(a[i].y,10)) continue;
                for (k=1;k<=all;++k)
                {
                    if (LINE[k].point1==a[i]||LINE[k].point1==a[j]||LINE[k].point2==a[i]||LINE[k].point2==a[j]) continue;
                    if (SegmentIntersect(a[i],a[j],LINE[k].point1,LINE[k].point2)) break;
                }
                if (k==all+1) e[i][j]=e[j][i]=dis(a[i],a[j]);
            }
        }
        for (int i=1;i<=num;++i)
        {
            for (int j=1;j<=num;j++)
            {
                for (int k=1;k<=num;++k)
                {
                    if (e[j][k]>e[j][i]+e[i][k]) e[j][k]=e[j][i]+e[i][k];
                }
            }
        }
        printf ("%0.2f
    ",e[num-1][num]);
        //printf ("%0.2f
    ",e[num-1][1]);
        return;
    }
    
    int main()
    {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        while(scanf("%d",&n)!=EOF && n!=-1) work();
        return 0;
    }
    View Code
  • 相关阅读:
    12.3
    团队项目第一阶段冲刺第一天
    4.22
    4.21 re重要功能
    12.1
    12.2
    4.17
    4.16
    css设置子元素相对于父元素保持位置不变(含有滚动条的父元素)
    git操作和npm操作清单
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5759919.html
Copyright © 2020-2023  润新知