• poj1556


    题意:一个正方形密室边长是10,内部有平行y轴方向的n堵墙,每堵墙都有两道门。要从(0,5)走到(10,5)最短距离是多少?

    分析:每道门的两个端点以及起点终点作为节点,要求起点到终点的最短路,建图时结合线段相交来判断两个顶点之间是否可达,就枚举这两个顶点之间的墙与这两个顶点相连而成的线段有没有相交,相交则不可达,不相交则为这线段的长度。Dijkstra + 线段相交判断,数据的组织要清晰。

    #include<cstdio>
    #include<cmath>
    #define vector point
    struct point
    {
        double x,y;
        point(double xx = 0,double yy = 0)
        {
            x = xx;
            y = yy;
        }
        point operator - (point s)
        {
            return point(x - s.x, y - s.y);
        }
    };
    
    //叉积
    double cross_product(vector v1,vector v2)
    {
        return v1.x * v2.y - v1.y * v2.x;
    }
    
    //线段
    struct segment
    {
        point end[2];
        segment(point p1 = point(0,0),point p2 = point(0,0))
        {
            end[0] = p1;
            end[1] = p2;
        }
    };
    
    segment seg[18][3];
    point node[18][4];
    int n;
    bool tag[101];//tag[]是否访问过的标志
    double matrix[101][101],dis[101];//dis存储当前从起点到该点的最短距离
    const point sp = point(0,5),ep = point(10,5);
    
    void dijkstra(int start)//start是出发点
    {
        int i,j,min_N;
        for(i=0;i<n * 4 + 2;i++)
        {
            dis[i]=matrix[start][i];
            tag[i]=false;
        }
        tag[start]=true;
        dis[start]=1e10;
        for(j=0;j<n * 4 + 2;j++)
        {
            min_N=start;
            for(i=0;i<n * 4 + 2;i++)
            {
                if(!tag[i])
                {
                    if(dis[min_N]>dis[i])
                        min_N=i;
                }
            }
            //更新标志和距离
            if(min_N!=start)
            {
                tag[min_N]=true;
                for(i=0;i<n * 4 + 2;i++)
                {
                    if(!tag[i] && dis[i]>matrix[min_N][i]+dis[min_N])
                        dis[i]=matrix[min_N][i]+dis[min_N];
                }
            }
            else
                break;            
        }
    }
    
    //线段相交判断(跨立试验)
    bool intersect(segment seg1,segment seg2)
    {
        if(cross_product(vector(seg2.end[0] - seg1.end[0]),vector(seg1.end[1] - seg1.end[0])) * 
            cross_product(vector(seg1.end[1] - seg1.end[0]),vector(seg2.end[1] - seg1.end[0])) <= 0)
            return false;
        if(cross_product(vector(seg1.end[0] - seg2.end[0]),vector(seg2.end[1] - seg2.end[0])) *
            cross_product(vector(seg2.end[1] - seg2.end[0]),vector(seg1.end[1] - seg2.end[0])) <= 0)
            return false;
        return true;
    }
    
    int toNum(int x,int y)
    {
        return x * 4 + y + 1;
    }
    
    double distance(point p1,point p2)
    {
        vector v = p1 - p2;
        return sqrt(v.x * v.x + v.y * v.y);
    }
    int main()
    {
        while(scanf("%d",&n) && n != -1)
        {
            for(int i = 0;i < n;i++)
            {
                double x,y;
                scanf("%lf",&x);
                for(int j = 0;j < 4;j++)
                {
                    scanf("%lf",&y);
                    node[i][j] = point(x,y);
                    switch(j)
                    {
                    case 0:
                        seg[i][0] = segment(point(x,0),node[i][j]);
                        break;
                    case 2:
                        seg[i][1] = segment(node[i][j - 1],node[i][j]);
                        break;
                    case 3:
                        seg[i][2] = segment(node[i][j],point(x,10));
                    }
                }
            }
    
            //建图
            for(int i = 0;i < n * 4 + 2;i++)
            {
                for(int j = 0;j < n * 4 + 2;j++)
                    matrix[i][j] = 1e10;
                matrix[i][i] = 0;
            }
    
            for(int i = 0;i < n;i++)
            {
                for(int j = 0;j < 4;j++)
                {
                    bool flag = true;
                    for(int k = 0;k < i;k++)
                    {
                        for(int m = 0;m < 3;m++)
                        {
                            if(intersect(segment(sp,node[i][j]),seg[k][m]))
                            {
                                flag = false;
                                break;
                            }
                        }
                        if(!flag)
                            break;
                    }
                    if(flag)
                        matrix[0][toNum(i,j)] = distance(sp,node[i][j]);
                }
            }
    
            bool flag = true;
            for(int k = 0;k < n;k++)
            {
                for(int m = 0;m < 3;m++)
                {
                    if(intersect(segment(sp,ep),seg[k][m]))
                    {
                        flag = false;
                        break;
                    }
                }
                if(!flag)
                    break;
            }
            if(flag)
                matrix[0][n * 4 + 1] = distance(sp,ep);
    
            for(int x = 0;x < n;x++)
            {
                for(int y = 0;y < 4;y++)
                {
                    //以上是起点
                    for(int i = x + 1;i < n;i++)
                    {
                        for(int j = 0;j < 4;j++)
                        {
                            //以上是终点
                            bool flag = true;
                            for(int k = x + 1;k < i;k++)
                            {
                                for(int m = 0;m < 3;m++)
                                {
                                    if(intersect(segment(node[x][y],node[i][j]),seg[k][m]))
                                    {
                                        flag = false;
                                        break;
                                    }
                                }
                                if(!flag)
                                    break;
                            }
                            if(flag)
                                matrix[toNum(x,y)][toNum(i,j)] = distance(node[x][y],node[i][j]);
                        }
                    }
    
                    bool flag = true;
                    for(int k = x + 1;k < n;k++)
                    {
                        for(int m = 0;m < 3;m++)
                        {
                            if(intersect(segment(node[x][y],ep),seg[k][m]))
                            {
                                flag = false;
                                break;
                            }
                        }
                        if(!flag)
                            break;
                    }
                    if(flag)
                        matrix[toNum(x,y)][n * 4 + 1] = distance(node[x][y],ep);
                }
            }
            dijkstra(0);
            printf("%.2lf\n",dis[n * 4 + 1]);
        }
        return 0;
    }
  • 相关阅读:
    高可用网站多点部署架构实战经验总结
    使用阿里云发送邮件完美解决 端口 25 465
    阿里云 SSL 证书 总结
    支付宝支付接入流程
    阿里云服务器ECS的环境部署和安装
    对接 第三方物流APP 手机版
    智付支付接入心得
    二次开发本地配置域名
    从1到n整数中1出现的次数:O(logn)算法
    MongoDB——增删改查
  • 原文地址:https://www.cnblogs.com/ZShogg/p/3053928.html
Copyright © 2020-2023  润新知