当前位置: 首页 > article >正文

Bellman-Ford 和 SPFA 算法的实现DEM路径搜索

首先,假设你已经有一个 2D 数组表示 DEM 数据,每个元素的值表示某个位置的高度。你可以根据特定的规则来决定哪些区域是障碍物或无效值。

  1. Bellman-Ford 算法的实现
#include <iostream>
#include <vector>
#include <climits>
#include <queue>

using namespace std;

// 定义一个邻接列表表示图
struct Edge {
    int u, v, weight;
};

class BellmanFord {
public:
    BellmanFord(int n) : V(n), dist(n, INT_MAX) {}

    void addEdge(int u, int v, int weight) {
        edges.push_back({u, v, weight});
    }

    // Bellman-Ford算法求最短路径
    void run(int start) {
        dist[start] = 0;

        // 放松所有边 V-1 次
        for (int i = 0; i < V - 1; ++i) {
            for (auto& edge : edges) {
                if (dist[edge.u] != INT_MAX && dist[edge.u] + edge.weight < dist[edge.v]) {
                    dist[edge.v] = dist[edge.u] + edge.weight;
                }
            }
        }

        // 检查负权环
        for (auto& edge : edges) {
            if (dist[edge.u] != INT_MAX && dist[edge.u] + edge.weight < dist[edge.v]) {
                cout << "Negative weight cycle detected!" << endl;
                return;
            }
        }
    }

    int getDistance(int vertex) {
        return dist[vertex];
    }

private:
    int V;
    vector<Edge> edges;
    vector<int> dist;
};

int main() {
    int V = 5; // 假设图中有5个节点
    BellmanFord bf(V);

    // 示例: 添加一些边
    bf.addEdge(0, 1, 10);
    bf.addEdge(0, 2, 5);
    bf.addEdge(1, 2, 2);
    bf.addEdge(1, 3, 1);
    bf.addEdge(2, 1, 3);
    bf.addEdge(2, 3, 9);
    bf.addEdge(3, 4, 4);

    int start = 0;  // 指定起点
    bf.run(start);

    // 输出从起点到每个点的最短距离
    for (int i = 0; i < V; ++i) {
        cout << "Distance from " << start << " to " << i << ": " << bf.getDistance(i) << endl;
    }

    return 0;
}
  1. SPFA (Shortest Path Faster Algorithm) 算法的实现
#include <iostream>
#include <vector>
#include <climits>
#include <queue>

using namespace std;

class SPFA {
public:
    SPFA(int n) : V(n), dist(n, INT_MAX), inQueue(n, false) {}

    void addEdge(int u, int v, int weight) {
        adj[u].push_back({v, weight});
    }

    void run(int start) {
        dist[start] = 0;
        queue<int> q;
        q.push(start);
        inQueue[start] = true;

        while (!q.empty()) {
            int u = q.front();
            q.pop();
            inQueue[u] = false;

            for (auto& edge : adj[u]) {
                int v = edge.first, weight = edge.second;
                if (dist[u] + weight < dist[v]) {
                    dist[v] = dist[u] + weight;
                    if (!inQueue[v]) {
                        q.push(v);
                        inQueue[v] = true;
                    }
                }
            }
        }
    }

    int getDistance(int vertex) {
        return dist[vertex];
    }

private:
    int V;
    vector<vector<pair<int, int>>> adj;  // 邻接表,存储边(目标节点,边的权重)
    vector<int> dist;
    vector<bool> inQueue;  // 判断节点是否已经在队列中
};

int main() {
    int V = 5;  // 假设图中有5个节点
    SPFA spfa(V);

    // 示例: 添加一些边
    spfa.addEdge(0, 1, 10);
    spfa.addEdge(0, 2, 5);
    spfa.addEdge(1, 2, 2);
    spfa.addEdge(1, 3, 1);
    spfa.addEdge(2, 1, 3);
    spfa.addEdge(2, 3, 9);
    spfa.addEdge(3, 4, 4);

    int start = 0;  // 指定起点
    spfa.run(start);

    // 输出从起点到每个点的最短距离
    for (int i = 0; i < V; ++i) {
        cout << "Distance from " << start << " to " << i << ": " << spfa.getDistance(i) << endl;
    }

    return 0;
}
  1. 处理 DEM 数据和障碍物
    你可以将 DEM 数据表示为一个二维数组,每个位置的值是该位置的高度。假设高度低于某个阈值的区域表示障碍物或无效值。

#include <iostream>
#include <vector>

using namespace std;

bool isObstacle(int height, int threshold) {
    return height <= threshold;
}

void buildGraphFromDEM(const vector<vector<int>>& dem, int threshold, SPFA& spfa) {
    int rows = dem.size();
    int cols = dem[0].size();

    // 邻接表构建
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            if (isObstacle(dem[i][j], threshold)) {
                continue;  // 如果是障碍物或无效值,则跳过
            }

            // 将四个方向的邻接节点添加到图中
            if (i > 0 && !isObstacle(dem[i - 1][j], threshold)) {  // 上
                spfa.addEdge(i * cols + j, (i - 1) * cols + j, 1);
            }
            if (i < rows - 1 && !isObstacle(dem[i + 1][j], threshold)) {  // 下
                spfa.addEdge(i * cols + j, (i + 1) * cols + j, 1);
            }
            if (j > 0 && !isObstacle(dem[i][j - 1], threshold)) {  // 左
                spfa.addEdge(i * cols + j, i * cols + (j - 1), 1);
            }
            if (j < cols - 1 && !isObstacle(dem[i][j + 1], threshold)) {  // 右
                spfa.addEdge(i * cols + j, i * cols + (j + 1), 1);
            }
        }
    }
}

int main() {
    vector<vector<int>> dem = {
        {1, 1, 1, 0, 1},
        {1, 0, 1, 1, 1},
        {1, 1, 0, 1, 0},
        {1, 1, 1, 1, 1}
    };
    int threshold = 0;  // 假设 0 以下为障碍物
    int V = dem.size() * dem[0].size();
    SPFA spfa(V);

    buildGraphFromDEM(dem, threshold, spfa);

    int start = 0;  // 从 (0, 0) 点出发
    spfa.run(start);

    // 输出从起点到目标点的最短距离
    int target = 4;  // 比如目标点为 (0, 4)
    cout << "Distance from start to target: " << spfa.getDistance(target) << endl;

    return 0;
}

代码解释:
Bellman-Ford 算法:该算法是用于解决单源最短路径问题的经典算法。它逐步放松所有的边
𝑉

1
V−1 次,适用于带负权边的情况。
SPFA 算法:SPFA 是一种基于队列的改进算法,它在大多数情况下比 Bellman-Ford 快。
DEM 数据处理:通过 isObstacle 函数判断高度是否低于给定的阈值,从而判断是否为障碍物。如果是障碍物,则不添加边。
运行:
程序会自动过滤掉无效区域(障碍物)并计算从起点到终点的最短路径。
可以通过修改 dem 和 threshold 来适配不同的地图和障碍物条件。
如果你有特定的数据或者需要进一步的功能扩展,随时告诉我!


http://www.kler.cn/a/401615.html

相关文章:

  • C++AVL平衡树
  • 散户持股增厚工具:智能T0算法交易
  • 初学者编程语言的选择
  • 【HarmonyOS】鸿蒙系统在租房项目中的项目实战(一)
  • 大模型呼叫中心,如何建设呼入机器人系统?
  • 【MySql】实验十六 综合练习:图书管理系统数据库结构
  • 小米顾此失彼:汽车毛利大增,手机却跌至低谷
  • git使用流程梳理
  • 前馈神经网络 (Feedforward Neural Network, FNN)
  • 如何理解Lua 使用虚拟堆栈
  • Windows11暂停更新(超长延期)
  • html5 实现视频播放
  • 【设计模式】模板方法模式 在java中的应用
  • javaScript交互补充3(JSON数据)
  • JavaEE-多线程基础知识
  • C++ ─── 哈希表(unordered_set 和unordered_map) 开散列和闭散列的模拟实现
  • 搜维尔科技:基于Touch力反馈与VR技术的虚拟气管切开术的虚拟操作软件平台
  • CentOS 环境下通过 YUM 安装软件
  • OpenAI 助力数据分析中的模式识别与趋势预测
  • 疫情期间基于Spring Boot的图书馆管理系统
  • 基于yolov8、yolov5的行人检测识别系统(含UI界面、训练好的模型、Python代码、数据集)
  • Vue所有图片预加载加上Token请求头信息、图片请求加载鉴权
  • 小米运动健康与华为运动健康在苹手机ios系统中无法识别蓝牙状态 (如何在ios系统中开启 蓝牙 相册 定位 通知 相机等功能权限,保你有用)
  • 23种设计模式-模板方法(Template Method)设计模式
  • Unix发展历程的深度探索
  • 时代变迁对传统机器人等方向课程的巨大撕裂