2020ICPC·小米 网络选拔赛第一场 B Intelligent Robot(判断线段是否相交)

题意:
k条直线,不能越过直线,从起点到终点最短距离是多少。

思路:
对每个直线上的点加上起点终点,如果两点的直线不与其他直线有交点,那么就建边。
之后dij算出到每个点的最短距离即可。

tips:
两条直线AB,CD,要判断AB是否与CD相交,只需要判断A,B是否在CD两侧,且C,D是否在AB两侧。

则有 ABAC与ABAD异号(向量叉乘),CDCA与CDCB异号。

#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>

using namespace std;

typedef long long ll;
const int maxn = 1000 + 7;
const double eps = 1e-6;

int n,m,k;
vector<pair<int,double> >G[maxn];

struct Point {
    
    
    double x,y;
    Point(){
    
    }
    Point(double x,double y) {
    
    
        this -> x = x;
        this -> y = y;
    }
    Point operator+(Point a)
    {
    
    
        return Point(x + a.x,y + a.y);
    }
    Point operator-(Point a)
    {
    
    
        return Point(x - a.x,y - a.y);
    }
    Point operator*(double t)
    {
    
    
        return Point(x * t,y * t);
    }
    double operator*(Point a)
    {
    
    
        return x * a.y - y * a.x;
    }
    Point operator/(double t)
    {
    
    
        return Point(x / t,y / t);
    }
    double operator^(Point a)
    {
    
    
        return x * a.x + y * a.y;
    }
    double vl()
    {
    
    
        return sqrt(x * x + y * y);
    }
}sta,ed;


double dis(Point p1,Point p2) {
    
    
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}


struct Line {
    
    
    Point a,b;
    Line(){
    
    };
    Line(Point a,Point b) {
    
    
        this -> a = a;
        this -> b = b;
    }
    double Len() {
    
    
        return dis(a,b);
    }
}a[maxn];

Point Intersection(Line X,Line Y) {
    
     //算直线交点
    Point v = X.a - X.b;
    Point w = Y.a - Y.b;
    Point u = X.a - Y.a;
    double t = (w * u) / (v * w);
    return X.a + v * t;
}

int same(double x,double y) {
    
    
    if(fabs(x - y) < eps) return true;
    return false;
}

int sign(double x) {
    
    
    if(x < -eps) {
    
    
        return -1;
    } else if(x > eps) return 1;
    return 0;
}

bool judge(Line line) {
    
     //是否和其他直线有交点,且交点不是端点,判断线段是否相交
    for(int i = 1;i <= k;i++) {
    
    
        Point AD = line.a - a[i].a;
        Point AC = line.a - a[i].b;
        Point AB = line.a - line.b;
        
        Point CA = a[i].a - line.a;
        Point CB = a[i].a - line.b;
        Point CD = a[i].a - a[i].b;
        if((CD * CA) * (CD * CB) < 0 && (AB * AC) * (AB * AD) < 0) {
    
    
            return true;
        }
    }
    return false;
}

int head[maxn],nex[maxn * maxn],to[maxn * maxn],tot;
double val[maxn * maxn];

void add(int x,int y,double z) {
    
    
    to[++tot] = y;
    nex[tot] = head[x];
    val[tot] = z;
    head[x] = tot;
    
    to[++tot] = x;
    nex[tot] = head[y];
    val[tot] = z;
    head[y] = tot;
}

double d[maxn];
int vis[maxn];

void dij() {
    
    
    priority_queue<pair<double,int> >q;
    q.push({
    
    0,0});
    for(int i = 0;i < maxn;i++) d[i] = 1e18;
    d[0] = 0;
    while(!q.empty()) {
    
    
        pair<double,int> now = q.top();q.pop();
        int x = now.second;
        if(vis[x]) continue;
        vis[x] = 1;
        for(int i = head[x];i;i = nex[i]) {
    
    
            int v = to[i];
            double w = val[i];
            if(d[v] > d[x] + w) {
    
    
                d[v] = d[x] + w;
                q.push({
    
    -d[v],v});
            }
        }
    }
}

int main() {
    
    
    scanf("%d%d%d",&n,&m,&k);
    vector<Point>vec;
    for(int i = 1;i <= k;i++) {
    
    
        Point p1,p2;
        scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
        a[i].a = p1;a[i].b = p2;
    }
    scanf("%lf%lf%lf%lf",&sta.x,&sta.y,&ed.x,&ed.y);
    vec.push_back(sta);
    for(int i = 1;i <= k;i++) {
    
    
        vec.push_back(a[i].a);
        vec.push_back(a[i].b);
        add(vec.size() - 2,vec.size() - 1,a[i].Len());
    }
    vec.push_back(ed);
    
    for(int i = 0;i < vec.size();i++) {
    
    
        for(int j = i + 1;j < vec.size();j++) {
    
     //从i到j建边
            Line line = Line(vec[i],vec[j]);
            double len = dis(vec[i],vec[j]);
            if(!judge(line)) {
    
    
                add(i,j,len);
//                printf("%d %d\n",i,j);
            }
        }
    }
    
    dij();
    printf("%.4f\n",d[vec.size() - 1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/109281064