1 条题解

  • 0
    @ 2025-4-9 22:07:26

    题意分析

    Mothy 需要在牛仔裤的表面上找到一条最短路径,从他所在的位置到他母亲的位置。牛仔裤上有多个补丁(凸多边形),Mothy 不能穿过补丁的内部,但可以在补丁的边缘移动。

    解题思路

    1. 图的构建

      • 将 Mothy 的位置、他母亲的位置以及所有补丁的顶点视为图的节点。
      • 如果两个节点之间可以直接通过牛仔裤表面移动(不穿过任何补丁),则在它们之间添加一条边,权重为两点之间的欧几里得距离。
    2. 最短路径算法

      • 使用 Dijkstra 算法或 A* 算法计算从 Mothy 的位置到他母亲的位置的最短路径。
    3. 障碍物检测

      • 在构建图时,需要检测路径是否穿过任何补丁的内部。如果是,则不能添加这条边。
    4. 输出结果

      • 如果找到最短路径,则输出其长度,保留三位小数。
      • 如果无法找到路径,则输出 1-1

    C++ 代码实现

    #include <iostream>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <iomanip>
    
    using namespace std;
    
    struct Point {
        double x, y;
        Point(double x = 0, double y = 0) : x(x), y(y) {}
    };
    
    // 计算两点之间的欧几里得距离
    double distance(const Point& p1, const Point& p2) {
        return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
    }
    
    // 检查线段是否与多边形相交
    bool isSegmentIntersectPolygon(const Point& p1, const Point& p2, const vector<Point>& polygon) {
        // 实现线段与多边形的相交检测
        // 这里省略具体实现
        return false;
    }
    
    int main() {
        int T;
        cin >> T;
        while (T--) {
            int N;
            Point start, end;
            cin >> N >> start.x >> start.y >> end.x >> end.y;
    
            vector<vector<Point>> patches(N);
            for (int i = 0; i < N; ++i) {
                int vertices;
                cin >> vertices;
                patches[i].resize(vertices);
                for (int j = 0; j < vertices; ++j) {
                    cin >> patches[i][j].x >> patches[i][j].y;
                }
            }
    
            // 构建图的节点
            vector<Point> nodes = {start, end};
            for (const auto& patch : patches) {
                for (const auto& vertex : patch) {
                    nodes.push_back(vertex);
                }
            }
    
            // 构建图的边
            vector<vector<pair<int, double>>> graph(nodes.size());
            for (int i = 0; i < nodes.size(); ++i) {
                for (int j = i + 1; j < nodes.size(); ++j) {
                    bool canConnect = true;
                    for (const auto& patch : patches) {
                        if (isSegmentIntersectPolygon(nodes[i], nodes[j], patch)) {
                            canConnect = false;
                            break;
                        }
                    }
                    if (canConnect) {
                        double dist = distance(nodes[i], nodes[j]);
                        graph[i].emplace_back(j, dist);
                        graph[j].emplace_back(i, dist);
                    }
                }
            }
    
            // Dijkstra 算法计算最短路径
            vector<double> dist(nodes.size(), 1e9);
            dist[0] = 0;
            priority_queue<pair<double, int>, vector<pair<double, int>>, greater<pair<double, int>>> pq;
            pq.emplace(0, 0);
    
            while (!pq.empty()) {
                double d = pq.top().first;
                int u = pq.top().second;
                pq.pop();
    
                if (d > dist[u]) continue;
    
                for (const auto& edge : graph[u]) {
                    int v = edge.first;
                    double w = edge.second;
                    if (dist[v] > dist[u] + w) {
                        dist[v] = dist[u] + w;
                        pq.emplace(dist[v], v);
                    }
                }
            }
    
            // 输出结果
            if (dist[1] < 1e9) {
                cout << fixed << setprecision(3) << dist[1] << endl;
            } else {
                cout << -1 << endl;
            }
        }
        return 0;
    }
    

    代码解释

    1. Point 结构体

      • 表示平面中的一个点。
    2. distance 函数

      • 计算两点之间的欧几里得距离。
    3. isSegmentIntersectPolygon 函数

      • 检查线段是否与多边形相交(具体实现省略)。
    4. 图的构建

      • 将 Mothy 的位置、他母亲的位置以及所有补丁的顶点作为图的节点。
      • 如果两个节点之间的路径不穿过任何补丁,则在它们之间添加一条边。
    5. Dijkstra 算法

      • 计算从 Mothy 的位置到他母亲的位置的最短路径。
    6. 输出结果

      • 如果找到最短路径,则输出其长度,保留三位小数。
      • 如果无法找到路径,则输出 1-1

    复杂度分析

    1. 时间复杂度

      • 构建图的时间复杂度为 O(NV2)O(N \cdot V^2),其中 NN 是补丁数量,VV 是顶点总数。
      • Dijkstra 算法的时间复杂度为 O(V2logV)O(V^2 \log V)
    2. 空间复杂度

      • 需要 O(V2)O(V^2) 的空间存储图。

    总结

    通过构建图和使用 Dijkstra 算法,我们可以高效地计算 Mothy 的最短路径,确保他能够以最快的方式找到他的母亲。

    • 1

    信息

    ID
    1678
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者