代码随想录学习 54day 图论 Bellman_ford 算法精讲

Bellman_ford 算法精讲

卡码网:94. 城市间货物运输 I
题目描述
某国为促进城市间经济交流,决定对货物运输提供补贴。共有 n 个编号为 1 到 n 的城市,通过道路网络连接,网络中的道路仅允许从某个城市单向通行到另一个城市,不能反向通行。网络中的道路都有各自的运输成本和政府补贴,道路的权值计算方式为:运输成本 - 政府补贴。权值为正表示扣除了政府补贴后运输货物仍需支付的费用;权值为负则表示政府的补贴超过了支出的运输成本,实际表现为运输过程中还能赚取一定的收益。请找出从城市 1 到城市 n 的所有可能路径中,综合政府补贴后的最低运输成本。如果最低运输成本是一个负数,它表示在遵循最优路径的情况下,运输过程中反而能够实现盈利。城市 1 到城市 n 之间可能会出现没有路径的情况,同时保证道路网络中不存在任何负权回路。负权回路是指一系列道路的总权值为负,这样的回路使得通过反复经过回路中的道路,理论上可以无限地减少总成本或无限地增加总收益。输入描述第一行包含两个正整数,第一个正整数 n 表示该国一共有 n 个城市,第二个整数 m 表示这些城市中共有 m 条道路。接下来为 m 行,每行包括三个整数,s、t 和 v,表示 s 号城市运输货物到达 t 号城市,道路权值为 v(单向图)。输出描述如果能够从城市 1 到连通到城市 n, 请输出一个整数,表示运输成本。如果该整数是负数,则表示实现了盈利。如果从城市 1 没有路径可达城市 n,请输出 "unconnected"。输入示例:6 7
5 6 -2
1 2 1
5 3 1
2 5 2
2 4 -3
4 6 4
1 3 5

思路

本题依然是单源最短路问题,求 从 节点1 到节点n 的最小费用。 但本题不同之处在于 边的权值是有负数了。从 节点1 到节点n 的最小费用也可以是负数,费用如果是负数 则表示 运输的过程中 政府补贴大于运输成本。在求单源最短路的方法中,使用dijkstra 的话,则要求图中边的权值都为正数。我们在 dijkstra朴素版 中专门有讲解:为什么有边为负数 使用dijkstra就不行了。本题是经典的带负权值的单源最短路问题,此时就轮到Bellman_ford登场了,接下来我们来详细介绍Bellman_ford 算法 如何解决这类问题。该算法是由 R.Bellman 和L.Ford 在20世纪50年代末期发明的算法,故称为Bellman_ford算法。Bellman_ford算法的核心思想是 对所有边进行松弛n-1次操作(n为节点数量),从而求得目标最短路。

什么叫做松弛

看到这里,估计大家都比较晕了,为什么是 n-1 次,那“松弛”这两个字究竟是个啥意思?我们先来说什么是 “松弛”。《算法四》里面把这个操作叫做 “放松”, 英文版里叫做 “relax the edge”所以大家翻译过来,就是 “放松” 或者 “松弛” 。但《算法四》没有具体去讲这个 “放松” 究竟是个啥? 网上很多题解也没有讲题解里的 “松弛这条边,松弛所有边”等等 里面的 “松弛” 究竟是什么意思?这里我给大家举一个例子,每条边有起点、终点和边的权值。例如一条边,节点A 到 节点B 权值为value,如图:minDist[B] 表示 到达B节点 最小权值,minDist[B] 有哪些状态可以推出来?状态一: minDist[A] + value 可以推出 minDist[B] 状态二: minDist[B]本身就有权值 (可能是其他边链接的节点B 例如节点C,以至于 minDist[B]记录了其他边到minDist[B]的权值)minDist[B] 应为如何取舍。本题我们要求最小权值,那么 这两个状态我们就取最小的if (minDist[B] > minDist[A] + value) minDist[B] = minDist[A] + value也就是说,如果 通过 A 到 B 这条边可以获得更短的到达B节点的路径,即如果 minDist[B] > minDist[A] + value,那么我们就更新 minDist[B] = minDist[A] + value ,这个过程就叫做 “松弛” 。以上讲了这么多,其实都是围绕以下这句代码展开:if (minDist[B] > minDist[A] + value) minDist[B] = minDist[A] + value这句代码就是 Bellman_ford算法的核心操作。以上代码也可以这么写:minDist[B] = min(minDist[A] + value, minDist[B])如果大家看过代码随想录的动态规划章节,会发现 无论是背包问题还是子序列问题,这段代码(递推公式)出现频率非常高的。其实 Bellman_ford算法 也是采用了动态规划的思想,即:将一个问题分解成多个决策阶段,通过状态之间的递归关系最后计算出全局最优解。(如果理解不了动态规划的思想也无所谓,理解我上面讲的松弛操作就好)那么为什么是 n - 1次 松弛呢?这里要给大家模拟一遍 Bellman_ford 的算法才行,接下来我们来看看对所有边松弛 n - 1 次的操作是什么样的。我们依然使用minDist数组来表达 起点到各个节点的最短距离,例如minDist[3] = 5 表示起点到达节点3 的最小距离为5

模拟过程

初始化过程。起点为节点1, 起点到起点的距离为0,所以 minDist[1] 初始化为0其他节点对应的minDist初始化为max,因为我们要求最小距离,那么还没有计算过的节点 默认是一个最大数,这样才能更新最小距离。对所有边 进行第一次松弛: (什么是松弛,在上面我已经详细讲过)以示例给出的所有边为例:5 6 -2
1 2 1
5 3 1
2 5 2
2 4 -3
4 6 4
1 3 5接下来我们来松弛一遍所有的边。边:节点5 -> 节点6,权值为-2 ,minDist[5] 还是默认数值max,所以不能基于 节点5 去更新节点6,如图:(在复习一下,minDist[5] 表示起点到节点5的最短距离)边:节点1 -> 节点2,权值为1 ,minDist[2] > minDist[1] + 1 ,更新 minDist[2] = minDist[1] + 1 = 0 + 1 = 1 ,如图:边:节点5 -> 节点3,权值为1 ,minDist[5] 还是默认数值max,所以不能基于节点5去更新节点3 如图:边:节点2 -> 节点5,权值为2 ,minDist[5] > minDist[2] + 2 (经过上面的计算minDist[2]已经不是默认值,而是 1),更新 minDist[5] = minDist[2] + 2 = 1 + 2 = 3 ,如图:边:节点2 -> 节点4,权值为-3 ,minDist[4] > minDist[2] + (-3),更新 minDist[4] = minDist[2] + (-3) = 1 + (-3) = -2 ,如图:边:节点4 -> 节点6,权值为4 ,minDist[6] > minDist[4] + 4,更新 minDist[6] = minDist[4] + 4 = -2 + 4 = 2边:节点1 -> 节点3,权值为5 ,minDist[3] > minDist[1] + 5,更新 minDist[3] = minDist[1] + 5 = 0 + 5 = 5 ,如图:以上是对所有边进行一次松弛之后的结果。那么需要对所有边松弛几次才能得到 起点(节点1) 到终点(节点6)的最短距离呢?对所有边松弛一次,相当于计算 起点到达 与起点一条边相连的节点 的最短距离。上面的距离中,我们得到里 起点达到 与起点一条边相邻的节点2 和 节点3 的最短距离,分别是 minDist[2] 和 minDist[3]这里有录友疑惑了 minDist[3] = 5,分明不是 起点到达 节点3 的最短距离,节点1 -> 节点2 -> 节点5 -> 节点3 这条路线 距离才是4。注意我上面讲的是 对所有边松弛一次,相当于计算 起点到达 与起点一条边相连的节点 的最短距离,这里 说的是 一条边相连的节点。与起点(节点1)一条边相邻的节点,到达节点2 最短距离是 1,到达节点3 最短距离是5。而 节点1 -> 节点2 -> 节点5 -> 节点3 这条路线 是 与起点 三条边相连的路线了。
所以对所有边松弛一次 能得到 与起点 一条边相连的节点最短距离。那对所有边松弛两次 可以得到与起点 两条边相连的节点的最短距离。那对所有边松弛三次 可以得到与起点 三条边相连的节点的最短距离,这个时候,我们就能得到到达节点3真正的最短距离,也就是 节点1 -> 节点2 -> 节点5 -> 节点3 这条路线。那么再回归刚刚的问题,需要对所有边松弛几次才能得到 起点(节点1) 到终点(节点6)的最短距离呢?节点数量为n,那么起点到终点,最多是 n-1 条边相连。那么无论图是什么样的,边是什么样的顺序,我们对所有边松弛 n-1 次 就一定能得到 起点到达 终点的最短距离。其实也同时计算出了,起点 到达 所有节点的最短距离,因为所有节点与起点连接的边数最多也就是 n-1 条边。截止到这里,Bellman_ford 的核心算法思路,大家就了解的差不多了。共有两个关键点。“松弛”究竟是个啥?
为什么要对所有边松弛 n - 1 次 (n为节点个数) ?
那么Bellman_ford的解题解题过程其实就是对所有边松弛 n-1 次,然后得出得到终点的最短路径。

code c++ 1

理解上面讲解的内容,代码就更容易写了,本题代码如下:(详细注释)#include <iostream>
#include <vector>
#include <list>
#include <climits>
using namespace std;int main() {int n, m, p1, p2, val;cin >> n >> m;vector<vector<int>> grid;// 将所有边保存起来for(int i = 0; i < m; i++){cin >> p1 >> p2 >> val;// p1 指向 p2,权值为 valgrid.push_back({p1, p2, val});}int start = 1;  // 起点int end = n;    // 终点vector<int> minDist(n + 1 , INT_MAX);minDist[start] = 0;for (int i = 1; i < n; i++) { // 对所有边 松弛 n-1 次for (vector<int> &side : grid) { // 每一次松弛,都是对所有边进行松弛int from = side[0]; // 边的出发点int to = side[1]; // 边的到达点int price = side[2]; // 边的权值// 松弛操作// minDist[from] != INT_MAX 防止从未计算过的节点出发if (minDist[from] != INT_MAX && minDist[to] > minDist[from] + price) {minDist[to] = minDist[from] + price;}}}if (minDist[end] == INT_MAX) cout << "unconnected" << endl; // 不能到达终点else cout << minDist[end] << endl; // 到达终点最短路径}
时间复杂度: O(N * E) , N为节点数量,E为图中边的数量
空间复杂度: O(N) ,即 minDist 数组所开辟的空间关于空间复杂度,可能有录友疑惑,代码中数组grid不也开辟空间了吗? 为什么只算minDist数组的空间呢?grid数组是用来存图的,这是题目描述中必须要使用的空间,而不是我们算法所使用的空间。我们在讲空间复杂度的时候,一般都是说,我们这个算法所用的空间复杂度。

拓展

有录友可能会想,那我 松弛 n 次,松弛 n + 1次,松弛 2 * n 次会怎么样?其实没啥影响,结果不会变的,因为 题目中说了 “同时保证道路网络中不存在任何负权回路” 也就是图中没有 负权回路(在有向图中出现有向环 且环的总权值为负数)。那么我们只要松弛 n - 1次 就一定能得到结果,没必要在松弛更多次了。这里有疑惑的录友,可以加上打印 minDist数组 的日志,尝试一下,看看松弛 n 次会怎么样。你会发现 松弛 大于 n - 1次,minDist数组 就不会变化了。这里我给出打印日志的代码:

code c++ 打印日志

#include <iostream>
#include <vector>
#include <list>
#include <climits>
using namespace std;int main() {int n, m, p1, p2, val;cin >> n >> m;vector<vector<int>> grid;// 将所有边保存起来for(int i = 0; i < m; i++){cin >> p1 >> p2 >> val;// p1 指向 p2,权值为 valgrid.push_back({p1, p2, val});}int start = 1;  // 起点int end = n;    // 终点vector<int> minDist(n + 1 , INT_MAX);minDist[start] = 0;for (int i = 1; i < n; i++) { // 对所有边 松弛 n-1 次for (vector<int> &side : grid) { // 每一次松弛,都是对所有边进行松弛int from = side[0]; // 边的出发点int to = side[1]; // 边的到达点int price = side[2]; // 边的权值// 松弛操作// minDist[from] != INT_MAX 防止从未计算过的节点出发if (minDist[from] != INT_MAX && minDist[to] > minDist[from] + price) {minDist[to] = minDist[from] + price;}}cout << "对所有边松弛 " << i << "次" << endl;for (int k = 1; k <= n; k++) {cout << minDist[k] << " ";}cout << endl;}if (minDist[end] == INT_MAX) cout << "unconnected" << endl; // 不能到达终点else cout << minDist[end] << endl; // 到达终点最短路径}
通过打日志,大家发现,怎么对所有边进行第二次松弛以后结果就 不再变化了,那根本就不用松弛 n - 1 ?这是本题的样例的特殊性, 松弛 n-1 次 是保证对任何图 都能最后求得到终点的最小距离。如果还想不明白 我再举一个例子,用以下测试用例再跑一下。6 5
5 6 1
4 5 1
3 4 1
2 3 1
1 2 1打印结果:对所有边松弛 10 1 2147483647 2147483647 2147483647 2147483647
对所有边松弛 20 1 2 2147483647 2147483647 2147483647
对所有边松弛 30 1 2 3 2147483647 2147483647
对所有边松弛 40 1 2 3 4 2147483647
对所有边松弛 50 1 2 3 4 5
你会发现到 n-1 次 才打印出最后的最短路结果。关于上面的讲解,大家一定要多写代码去实验,验证自己的想法。至于 负权回路 ,我在下一篇会专门讲解这种情况,大家有个印象就好。

总结

Bellman_ford 是可以计算 负权值 的 单源 最短路 算法。其算法核心思路是对 所有边进行 n-1 次 松弛。 起点与起点n-1边相连的最短距离。弄清楚 什么是 松弛? 为什么要 n-1 次? 对理解Bellman_ford 非常重要。

code python 1

def main():n, m = [int(v) for v in input().split(' ')]grid = []for _ in range(m):v = [int(v) for v in input().split(' ')]grid.append(v)   # 将所有边保存起来  p1 指向 p2,权值为 valstart = 1  # 起点end = n  # 终点minDist = [float('Inf') for _ in range(n+1)]minDist[start] = 0  # 起点到起点的距离为 0for i in range(1, n): # n-1次松弛 起点 到终点1最多 n-1 条边for edge in grid:    # 每一次松弛,都是对所有边进行松弛s, t, price = edge   # 边的出发点, 边的到达点, 边的权值# 松弛操作# 防止从未计算过的节点开始出发# minDist[s] != float('Inf')if minDist[s] != float('Inf') and minDist[s] + price > minDist[t]:minDist[t] = minDist[s] + price# print(f"对所有边松弛{i}次")# for k in range(1, n+1):#     print(minDist[k], end=' ')# print('\n')if minDist[n] == float('Inf'):print('unconnected') # 不能到达终点else: print(minDist)   # 到达终点最短路径

code python 2 打印日志


def main1():# n, m = 6, 5# grid = [[5, 6, 1],[4, 5, 1],[3, 4, 1],[2, 3, 1],[1, 2, 1]]n, m = 6, 7grid = [[5, 6, -2],[1, 2, 1],[5, 3, 1],[2, 5, 2],[2, 4, -3],[4, 6, 4],[1, 3, 5]]start = 1  # 起点end = n  # 终点minDist = [float('Inf') for _ in range(n + 1)]minDist[start] = 0  # 起点到起点的距离为 0for i in range(1, n):  # n-1次松弛 起点 到终点1最多 n-1 条边for edge in grid:  # 每一次松弛,都是对所有边进行松弛s, t, price = edge  # 边的出发点, 边的到达点, 边的权值# 松弛操作# 防止从未计算过的节点开始出发# minDist[s] != float('Inf')if minDist[s] != float('Inf') and minDist[s] + price < minDist[t]:minDist[t] = minDist[s] + priceprint(f"对所有边松弛{i}次")for k in range(1, n + 1):print(minDist[k], end=' ')print('\n')if minDist[n] == float('Inf'):print('unconnected')  # 不能到达终点else:print(minDist)  # 到达终点最短路径

打印日志记录

"""n, m = 6, 5
grid = [[5, 6, 1],[4, 5, 1],[3, 4, 1],[2, 3, 1],[1, 2, 1]]对所有边松弛1次
0 1 inf inf inf inf
对所有边松弛2次
0 1 2 inf inf inf
对所有边松弛3次
0 1 2 3 inf inf
对所有边松弛4次
0 1 2 3 4 inf
对所有边松弛5次
0 1 2 3 4 5
[inf, 0, 1, 2, 3, 4, 5]n, m = 6, 7
grid = [[5, 6, -2],[1, 2, 1],[5, 3, 1],[2, 5, 2],[2, 4, -3],[4, 6, 4],[1, 3, 5]]
对所有边松弛1次
0 1 5 -2 3 2
对所有边松弛2次
0 1 4 -2 3 1
对所有边松弛3次
0 1 4 -2 3 1
对所有边松弛4次
0 1 4 -2 3 1
对所有边松弛5次
0 1 4 -2 3 1
[inf, 0, 1, 4, -2, 3, 1]
"""

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/47387.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代理IP服务中的代理池大小有何影响?

在当今数字化时代&#xff0c;网络爬虫已经成为获取各类信息必不可少的工具。在大规模数据抓取中&#xff0c;使用单一 IP 地址或同一 IP 代理往往会面临抓取可靠性降低、地理位置受限、请求次数受限等一系列问题。为了克服这些问题&#xff0c;构建代理池成为一种有效的解决方…

基于若依的ruoyi-nbcio流程管理系统修正自定义业务表单的回写bug

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; h…

VUE3 播放RTSP实时、回放(NVR录像机)视频流(使用WebRTC)

1、下载webrtc-streamer&#xff0c;下载的最新window版本 Releases mpromonet/webrtc-streamer GitHub 2、解压下载包 3、webrtc-streamer.exe启动服务 &#xff08;注意&#xff1a;这里可以通过当前文件夹下用cmd命令webrtc-streamer.exe -o这样占用cpu会很少&#xff0c…

idea Apipost 插件导出接口文档字段类型全部是string

idea版本&#xff1a;2023.2.1 Apipost-Helper-2.0插件版本&#xff1a; 联系官方客服后&#xff0c;更换插件版本&#xff0c;问题解决。更换后的插件版本为&#xff1a; 插件链接放在文章首部了&#xff0c;可直接下载&#xff0c;使用idea直接安装这个zip包&#xff0c;无需…

深度学习pytorch学到哪种程度就算入门了?

在开始前分享一些pytorch的资料需要的同学评论888即可拿走 是我根据网友给的问题精心整理的PyTorch这个框架&#xff0c;可以读一些入门书。 PyTorch本身是一个极其庞大的框架&#xff0c;里面有数据读取、高性能计算、自动微分、模型导出、分布式训练等等。 我觉得能用这个框…

ELK日志管理与应用

目录 一.ELK收集nginx日志 二.收集tomcat日志 三.Filebeat 一.ELK收集nginx日志 1.搭建好ELKlogstashkibana架构 2.关闭防火墙和selinux systemctl stop firewalld setenforce 0 3.安装nginx [rootlocalhost ~]# yum install epel-release.noarch -y [rootlocalhost …

使用Django框架实现音频上传功能

数据库设计&#xff08;models.py&#xff09; class Music(models.Model):""" 音乐 """name models.CharField(verbose_name"音乐名字", max_length32)singer models.CharField(verbose_name"歌手", max_length32)# 本质…

Hadoop-34 HBase 安装部署 单节点配置 hbase-env hbase-site 超详细图文 附带配置文件

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; HadoopHDFSMapReduceHiveFlumeSqoopZookeeperHBase 正在 章节内容 上节我们完成了&#xff1a; HBase的由…

Apache Paimon 在蚂蚁的应用

摘要 &#xff1a;本文整理自 Apache Paimon Committer 闵文俊老师在5月16日 Streaming Lakehouse Meetup Online 上的分享。内容主要分为以下四个部分&#xff1a; 什么是 Paimon蚂蚁 Paimon 应用场景蚂蚁 Paimon 功能改进未来规划 一、什么是 Paimon 1. 实时更新 Paimon 是…

Hadoop3:HDFS存储优化之小文件归档

一、情景说明 我们知道&#xff0c;NameNode存储一个文件元数据&#xff0c;默认是150byte大小的内存空间。 那么&#xff0c;如果出现很多的小文件&#xff0c;就会导致NameNode的内存占用。 但注意&#xff0c;存储小文件所需要的磁盘容量和数据块的大小无关。 例如&#x…

用户注册业务逻辑、接口设计和实现、前端逻辑

一、用户注册业务逻辑分析 二、用户注册接口设计和定义 2.1. 设计接口基本思路 对于接口的设计&#xff0c;我们要根据具体的业务逻辑&#xff0c;设计出适合业务逻辑的接口。设计接口的思路&#xff1a; 分析要实现的业务逻辑&#xff1a; 明确在这个业务中涉及到几个相关子…

如何通过企业微信会话存档保护企业利益?

赵总: 张经理&#xff0c;最近行业内频发数据泄露事件&#xff0c;我们的客户资料和内部沟通记录安全吗&#xff1f; 张经理: 赵总&#xff0c;我们已经采取了一系列措施来加强数据安全。特别是针对企业微信的沟通记录&#xff0c;我们最近引入了安企神软件&#xff0c;它能很…

构建管理大师:如何在Gradle中配置源代码目录

构建管理大师&#xff1a;如何在Gradle中配置源代码目录 在软件开发过程中&#xff0c;源代码目录的组织和管理是项目结构的重要组成部分。Gradle作为一个灵活且功能强大的构建工具&#xff0c;允许开发者自定义源代码目录&#xff0c;以适应不同的项目需求和开发习惯。本文将…

打印室预约小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;附近打印店管理&#xff0c;文件打印管理&#xff0c;当前预约管理&#xff0c;预约历史管理&#xff0c;打印记录管理 开发系统&#xff1a;Windows 架构模式&#xff1a;SSM JD…

神经网络构造

目录 一、神经网络骨架&#xff1a;二、卷积操作&#xff1a;三、卷积层&#xff1a;四、池化层&#xff1a;五、激活函数&#xff08;以ReLU为例&#xff09;&#xff1a; 一、神经网络骨架&#xff1a; import torch from torch import nn#神经网络 class CLH(nn.Module):de…

【乐吾乐2D可视化组态编辑器】事件

事件 乐吾乐2D可视化组态编辑器demo&#xff1a;https://2d.le5le.com/ 仅当画布锁定后(meta2d.store.data.locked 1 or 2)&#xff0c;触发事件。否则&#xff0c;干扰编辑。 定义 图元下的events属性为事件列表。 const pen {name: "rectangle",text: &qu…

华为的热机备份和流量限制

要求&#xff1a; 12&#xff0c;对现有网络进行改造升级&#xff0c;将当个防火墙组网改成双机热备的组网形式&#xff0c;做负载分担模式&#xff0c;游客区和DMZ区走FW4&#xff0c;生产区和办公区的流量走FW5 13&#xff0c;办公区上网用户限制流量不超过100M&#xff0c;…

Redis实战—附近商铺、用户签到、UV统计

本博客为个人学习笔记&#xff0c;学习网站与详细见&#xff1a;黑马程序员Redis入门到实战 P88 - P95 目录 附近商铺 数据导入 功能实现 用户签到 签到功能 连续签到统计 UV统计 附近商铺 利用Redis中的GEO数据结构实现附近商铺功能&#xff0c;常见命令如下图所示。…

vue3前端开发-如何让自己的网站适合SEO排名规则

vue3前端开发-如何让自己的网站适合SEO排名规则&#xff01;我们大家都知道&#xff0c;原始出生的vue3项目&#xff0c;原始代码层面&#xff0c;是没有meta标签的&#xff0c;也就是说&#xff0c;不适合SEO排名规则。那么我们能不能自己增加呢&#xff1f;答案是&#xff1a…

Photoneo 3D 网格划分

Photoneo 3D 网格划分是一种多功能软件解决方案&#xff0c;专为快速、精确的 3D 模型而设计 从多个 3D 扫描或来自 Photoneo 3D 传感器的连续 3D 数据流创建。它 旨在实现适用于各种应用的高级 3D 数据采集&#xff0c;例如 机器人引导、质量检查和逆向工程。 它以两个单独的库…