计算几何——判线段规范相交+最短路zoj1721

枚举每个端点,然后i点j点连线作为一条路径,逐一判断这条路径是否可行即可

注意的地方:判一条线段是否可行,需要判其余线段是否和其相交,但是这个相交比较难判(因为会不规范相交),所以将问题转化为墙以外的线是否和其相交,所有墙以外的线都要和其相交!

//判断线段相交
bool inter(Line l1,Line l2)
{
    return 
        max(l1.s.x,l1.e.x) > min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) > min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) > min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) > min(l1.s.y,l1.e.y) &&
        sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) < 0 &&
        sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) < 0;
}
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>

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;
    }
};
struct Line
{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e)
    {
        s = _s;e = _e;
    }
};
//判断线段相交
bool inter(Line l1,Line l2)
{
    return 
        max(l1.s.x,l1.e.x) > min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x) > min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y) > min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y) > min(l1.s.y,l1.e.y) &&
        sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) < 0 &&
        sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) < 0;
}
double dist(Point a,Point b)
{
    return sqrt((b-a)*(b-a));
}
const int MAXN = 500;
Line line[MAXN<<2];
Point p[MAXN<<2];
double dis[MAXN][MAXN];
const double INF = 1e20;
int n;

int check(Line tmp){
    for(int i=1;i<=3*n;i++)
        if(inter(tmp,line[i]))return 0;
    return 1;
}

int main(){
    double x,y1,y2,y3,y4;
    while(scanf("%d",&n) == 1)
    {
        if(n == -1) break;
        p[0]=Point(0,5),p[4*n+1]=Point(10,5);
        for(int i = 1;i <= n;i++)
        {
            scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);
            line[3*i-2] = Line(Point(x,0),Point(x,y1));
            line[3*i-1] = Line(Point(x,y2),Point(x,y3));
            line[3*i] = Line(Point(x,y4),Point(x,10));
            p[4*i-3]=Point(x,y1);
            p[4*i-2]=Point(x,y2);
            p[4*i-1]=Point(x,y3);
            p[4*i]=Point(x,y4);
        }
        for(int i = 0;i <= 4*n+1;i++)
            for(int j = 0;j <= 4*n+1;j++)
            {
                if(i == j)dis[i][j] = 0;
                else dis[i][j] = INF;
            }
        
        for(int i=0;i<=4*n+1;i++)
            for(int j=i+1;j<=4*n+1;j++){
                Line tmp=Line(p[i],p[j]);
                if(check(tmp))
                    dis[i][j]=dis[j][i]=dist(p[i],p[j]);
            }
        
        for(int k = 0;k <= 4*n+1;k++)
            for(int i = 0;i <= 4*n+1;i++)
                for(int j = 0;j <= 4*n+1;j++)
                    if(dis[i][k] + dis[k][j] < dis[i][j])
                        dis[i][j] = dis[i][k] + dis[k][j];
        printf("%.2lf
",dis[0][4*n+1]);
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/zsben991126/p/10923721.html