• POJ 1556 计算几何 判断线段相交 最短路


    题意:

    在一个左下角坐标为(0,0),右上角坐标为(10,10)的矩形内,起点为(0,5),终点为(10,5),中间会有许多扇垂直于x轴的门,求从起点到终点在能走的情况下的最短距离。

    分析:

    既然是求最短距离,很容易想到最短距离的算法。那么接下来就是构造图了,门的两端点为图中的一个结点(不包括边界点),总共有4*n+2个结点。

    枚举每一对结点连线,如果经过任意一张门,设距离为INF;否则距离就是它们的直线距离。

    数据量不大,直接FLoyd。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define eps 1e-8
    #define INF 1e9
    using namespace std;
    
    const int maxn=1000+5;
    double g[maxn][maxn];
    int n;
    
    typedef struct Point
    {
        double x,y;
        Point() {};
        Point(double xx,double yy)
        {
            x=xx;
            y=yy;
        }
    } Vector;
    
    Point pot[maxn];
    
    double crs_prdct(Vector a,Vector b)
    {
        return a.x*b.y-b.x*a.y;
    }
    
    double get_distance(Point a,Point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    Vector operator - (Point a,Point b)
    {
        return Vector(a.x-b.x,a.y-b.y);
    }
    
    bool intersect(Point p1,Point p2,Point q1,Point q2)
    {
        double crsp1=crs_prdct(q1-p1,q2-p1);
        double crsp2=crs_prdct(q1-p2,q2-p2);
        if(fabs(crsp1)<eps || fabs(crsp2)<eps) return true;
        return crsp1*crsp2<0? true:false;
    }
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        pot[0]=Point(0,5);
        while(scanf("%d",&n) && n!=-1)
        {
            double x,y1,y2,y3,y4;
            for(int i=0; i<n; i++)
            {
                scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);
                pot[4*i+1]=Point(x,y1);
                pot[4*i+2]=Point(x,y2);
                pot[4*i+3]=Point(x,y3);
                pot[4*i+4]=Point(x,y4);
            }
            pot[4*n+1]=Point(10,5);
            memset(g,0,sizeof(g));
            for(int i=0; i<4*n+2; i++)
            {
                for(int j=i+1; j<4*n+2; j++)
                {
                    int l=(i-1)/4,r=(j-1)/4;
                    if(i==0) l=-1;
                    bool flag=true;
                    for(int k=l+1; k<r; k++)
                    {
                        if(intersect(Point(pot[4*k+1].x,0),pot[4*k+1],pot[i],pot[j]))
                        {
                            flag=false;
                            break;
                        }
                        if(intersect(pot[4*k+2],pot[4*k+3],pot[i],pot[j]))
                        {
                            flag=false;
                            break;
                        }
                        if(intersect(pot[4*k+4],Point(pot[4*k+4].x,10),pot[i],pot[j]))
                        {
                            flag=false;
                            break;
                        }
                    }
                    g[i][j]=g[j][i]=(flag? get_distance(pot[i],pot[j]):INF);
                }
            }
            for(int k=0;k<4*n+2;k++)
                for(int i=0;i<4*n+2;i++)
                    for(int j=0;j<4*n+2;j++)
                        g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
            printf("%.2f
    ",g[0][4*n+1]);
        }
        return 0;
    }
  • 相关阅读:
    Socket 编程,一个服务器,多个客户端,互相通信(分享) 转
    rundll32.exe命令使用大全 转
    SQL操作全集 转
    看似简单!解读C#程序员最易犯的7大错误 转载
    使用ZedGraph制作动态更新的统计图 转
    C# 递归算法!(n多举例) 转
    C# WinForm开发系列 DataGridView 转载
    用 System.Xml 读写XML 整理文档 转载
    C# WinForm下动态创建的DataGridView更换表头字段名 转
    C# listview.add
  • 原文地址:https://www.cnblogs.com/pach/p/7211621.html
Copyright © 2020-2023  润新知