链接:https://ac.nowcoder.com/acm/contest/7501/B
思路:
只考虑特殊点即墙的端点,起点和终点。对于每个点都与另外的所有点尝试建边,建边的条件是这个边不会穿过墙。那么最后跑个最短路即可。
代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 610;

int head[maxn], tot;
double d[maxn];
bool vis[maxn];

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);
    }
    Point operator - (const Point &b)const{
        return Point(x-b.x,y-b.y);
    }
    Point operator * (const double &k)const{//乘常数
        return Point(x*k,y*k);
    }
    Point operator / (const double &k)const{
        return Point(x/k,y/k);
    }
    //点的叉积和点积都是数
    //点积
    double operator * (const Point &b)const{
        return x*b.x+y*b.y;
    }
    //叉积
    double operator ^ (const Point &b)const{
        return x*b.y-y*b.x;
    }

    double powlen(){return x*x+y*y;};

    double len(){return sqrt(powlen());}
}sta, ed;

inline 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 p1, Point p2) {
        this -> a = p1;
        this -> b = p2;
    }
    double Len() {
        return dis(a, b);
    }
}a[maxn];

struct Node{
    int u, v, nxt;
    double w;
}e[maxn * maxn];

struct A{
    int pos;
    double cost;
    bool operator < (const A &a1)const{
        return cost > a1.cost;
    }
};
int n, m, k;

bool judge(Line line) {
    for(int i = 1; i <= k; i++) {
        Point AB = line.b - line.a;
        Point AC = a[i].a - line.a;
        Point AD = a[i].b - line.a;

        Point CD = a[i].b - a[i].a;
        Point CB = line.b - a[i].a;
        Point CA = line.a - a[i].a;
        if((AB^AC)*(AB^AD) < 0 && (CD^CB)*(CD^CA) < 0) return true;
    }
    return false;
}


inline void add(int x, int y, double z)
{
    e[++tot].u = x;
    e[tot].v = y;
    e[tot].w = z;
    e[tot].nxt = head[x];
    head[x] = tot;
}

void dij(int src)
{
    for(int i = 0; i < 610; i++) d[i] = 1e18;
    memset(vis, 0, sizeof(vis));
    priority_queue<A>q;
    d[src] = 0;
    A now;
    now.cost = 0;
    now.pos = src;
    q.push(now);
    while(!q.empty())
    {
        now = q.top();
        q.pop();
        if(vis[now.pos])
            continue;
        vis[now.pos] = 1;
        for(int i = head[now.pos]; ~i; i = e[i].nxt)
        {
            int to = e[i].v;
            if(!vis[to] && d[to] > e[i].w + d[e[i].u])
            {
                d[to] = d[e[i].u] + e[i].w;
                now.cost = d[to];
                now.pos = to;
                q.push(now);
            }
        }
    }
}

int main()
{
    memset(head, -1, sizeof(head));
    vector<Point> vec;
    scanf("%d%d%d",&n,&m,&k);
    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);
    }
    vec.push_back(ed);
    int sz = vec.size();
    for(int i = 0; i < sz; i++) {
        for(int j = i+1; j < sz; j++) {
            Line line = Line(vec[i], vec[j]);
            if(!judge(line)) {
                double len = dis(vec[i], vec[j]);
//                cout << i << " " << j << " " <<len << endl;
                add(i, j, len);
                add(j, i, len);
            }
        }
    }
    dij(0);
    printf("%.4f\n",d[vec.size()-1]);

    return 0;
}