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

代码随想录学习 day54 图论 Bellman_ford 队列优化算法(又名SPFA) 学习

Bellman_ford 队列优化算法(又名SPFA)

卡码网: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

思路

背景
本题我们来系统讲解 Bellman_ford 队列优化算法 ,也叫SPFA算法(Shortest Path Faster Algorithm)。SPFA的称呼来自 1994年西南交通大学段凡丁的论文,其实Bellman_ford 提出后不久 (20世纪50年代末期) 就有队列优化的版本,国际上不承认这个算法是是国内提出的。 所以国际上一般称呼 该算法为 Bellman_ford 队列优化算法(Queue improved Bellman-Ford)大家知道以上来历,知道 SPFA 和 Bellman_ford 队列优化算法 指的都是一个算法就好。如果大家还不够了解 Bellman_ford 算法,强烈建议按照《代码随想录》的顺序学习,否则可能看不懂下面的讲解。Bellman_ford 算法每次松弛 都是对所有边进行松弛。但真正有效的松弛,是基于已经计算过的节点再做的松弛。给大家举一个例子:本图中,对所有边进行松弛,真正有效的松弛,只有松弛 边(节点1->节点2) 和 边(节点1->节点3) 。而松弛 边(节点4->节点6) ,边(节点5->节点3)等等 都是无效的操作,因为 节点4 和 节点 5 都是没有被计算过的节点。所以 Bellman_ford 算法 每次都是对所有边进行松弛,其实是多做了一些无用功。只需要对 上一次松弛的时候更新过的节点作为出发节点所连接的边进行松弛就够了。基于以上思路,如何记录 上次松弛的时候更新过的节点呢?用队列来记录。(其实用栈也行,对元素顺序没有要求)

模拟过程


接下来来举例这个队列是如何工作的。以示例给出的所有边为例:5 6 -2
1 2 1
5 3 1
2 5 2
2 4 -3
4 6 4
1 3 5我们依然使用minDist数组来表达 起点到各个节点的最短距离,例如minDist[3] = 5 表示起点到达节点3 的最小距离为5初始化,起点为节点1, 起点到起点的最短距离为0,所以minDist[1]0。 将节点1 加入队列 (下次松弛从节点1开始)从队列里取出节点1,松弛节点1 作为出发点连接的边(节点1 -> 节点2)和边(节点1 -> 节点3)边:节点1 -> 节点2,权值为1 ,minDist[2] > minDist[1] + 1 ,更新 minDist[2] = minDist[1] + 1 = 0 + 1 = 1 。边:节点1 -> 节点3,权值为5 ,minDist[3] > minDist[1] + 5,更新 minDist[3] = minDist[1] + 5 = 0 + 5 = 5。将节点2、节点3 加入队列,如图:从队列里取出节点2,松弛节点2 作为出发点连接的边(节点2 -> 节点4)和边(节点2 -> 节点5)边:节点2 -> 节点4,权值为1 ,minDist[4] > minDist[2] + (-3) ,更新 minDist[4] = minDist[2] + (-3) = 1 + (-3) = -2 。边:节点2 -> 节点5,权值为2 ,minDist[5] > minDist[2] + 2 ,更新 minDist[5] = minDist[2] + 2 = 1 + 2 = 3 。将节点4,节点5 加入队列,如图:从队列里出去节点3,松弛节点3 作为出发点连接的边。因为没有从节点3作为出发点的边,所以这里就从队列里取出节点3就好,不用做其他操作,如图:从队列中取出节点4,松弛节点4作为出发点连接的边(节点4 -> 节点6)边:节点4 -> 节点6,权值为4 ,minDist[6] > minDist[4] + 4,更新 minDist[6] = minDist[4] + 4 = -2 + 4 = 2 。将节点6加入队列从队列中取出节点5,松弛节点5作为出发点连接的边(节点5 -> 节点3),边(节点5 -> 节点6)边:节点5 -> 节点3,权值为1 ,minDist[3] > minDist[5] + 1 ,更新 minDist[3] = minDist[5] + 1 = 3 + 1 = 4边:节点5 -> 节点6,权值为-2 ,minDist[6] > minDist[5] + (-2) ,更新 minDist[6] = minDist[5] + (-2) = 3 - 2 = 1因为节点3 和 节点6 都曾经加入过队列,不用重复加入,避免重复计算。在代码中我们可以用一个数组 visited 来记录入过队列的元素,加入过队列的元素,不再重复入队列。从队列中取出节点6,松弛节点6 作为出发点连接的边。节点6作为终点,没有可以出发的边。所以直接从队列中取出,如图:这样我们就完成了基于队列优化的bellman_ford的算法模拟过程。大家可以发现 基于队列优化的算法,要比bellman_ford 算法 减少很多无用的松弛情况,特别是对于边数众多的大图 优化效果明显。了解了大体流程,我们再看代码应该怎么写。在上面模拟过程中,我们每次都要知道 一个节点作为出发点连接了哪些节点。如果想方便知道这些数据,就需要使用邻接表来存储这个图,如果对于邻接表不了解的话,可以看 kama0047.参会dijkstra堆 中 图的存储 部分。整体代码如下:

code c++ 1

#include <iostream>
#include <vector>
#include <queue>
#include <list>
#include <climits>
using namespace std;struct Edge { //邻接表int to;  // 链接的节点int val; // 边的权重Edge(int t, int w): to(t), val(w) {}  // 构造函数
};int main() {int n, m, p1, p2, val;cin >> n >> m;vector<list<Edge>> grid(n + 1); // 邻接表// 将所有边保存起来for(int i = 0; i < m; i++){cin >> p1 >> p2 >> val;// p1 指向 p2,权值为 valgrid[p1].push_back(Edge(p2, val));}int start = 1;  // 起点int end = n;    // 终点vector<int> minDist(n + 1 , INT_MAX);minDist[start] = 0;queue<int> que;que.push(start); // 队列里放入起点while (!que.empty()) {int node = que.front(); que.pop();  // 先取出元素,再删除元素for (Edge edge : grid[node]) {int from = node;int to = edge.to;int value = edge.val;if (minDist[to] > minDist[from] + value) { // 开始松弛minDist[to] = minDist[from] + value;que.push(to); // 松弛过的元素加入队列}}}if (minDist[end] == INT_MAX) cout << "unconnected" << endl; // 不能到达终点else cout << minDist[end] << endl; // 到达终点最短路径
}

效率分析

队列优化版Bellman_ford 的时间复杂度 并不稳定,效率高低依赖于图的结构。例如 如果是一个双向图,且每一个节点和所有其他节点都相连的话,那么该算法的时间复杂度就接近于 Bellman_ford 的 O(N * E) N 为节点数量,E为边的数量。在这种图中,每一个节点都会重复加入队列 n - 1次,因为 这种图中 每个节点 都有 n-1 条指向该节点的边,每条边指向该节点,就需要加入一次队列。(如果这里看不懂,可以在重温一下代码逻辑)至于为什么 双向图且每一个节点和所有其他节点都相连的话,每个节点 都有 n-1 条指向该节点的边, 我再来举个例子,如图:1<-------->2
^         ^
|         |
|         |
|         |
|         |
v         v
3<-------->4图中 每个节点都与其他所有节点相连,节点数n 为 4,每个节点都有3条指向该节点的边,即入度为3。n为其他数值的时候,也是一样的。当然这种图是比较极端的情况,也是最稠密的图。所以如果图越稠密,则 SPFA的效率越接近与 Bellman_ford。反之,图越稀疏,SPFA的效率就越高。一般来说,SPFA 的时间复杂度为 O(K * N) K 为不定值,因为 节点需要计入几次队列取决于 图的稠密度。如果图是一条线形图且单向的话,每个节点的入度为1,那么只需要加入一次队列,这样时间复杂度就是 O(N)。所以 SPFA 在最坏的情况下是 O(N * E),但 一般情况下 时间复杂度为 O(K * N)。尽管如此,以上分析都是 理论上的时间复杂度分析。并没有计算 出队列 和 入队列的时间消耗。 因为这个在不同语言上 时间消耗也是不一定的。以C++为例,以下两段代码理论上,时间复杂度都是 O(n)for (long long i = 0; i < n; i++) {k++;
}for (long long i = 0; i < n; i++) {que.push(i);que.front();que.pop();
}在 MacBook Pro (13-inch, M1, 2020) 机器上分别测试这两段代码的时间消耗情况:n = 10^4,第一段代码的时间消耗:1ms,第二段代码的时间消耗: 4 ms
n = 10^5,第一段代码的时间消耗:1ms,第二段代码的时间消耗: 13 ms
n = 10^6,第一段代码的时间消耗:4ms,第二段代码的时间消耗: 59 ms
n = 10^7,第一段代码的时间消耗: 24ms,第二段代码的时间消耗: 463 ms
n = 10^8,第一段代码的时间消耗: 135ms,第二段代码的时间消耗: 4268 ms
在这里就可以看出 出队列和入队列 其实也是十分耗时的。SPFA(队列优化版Bellman_ford) 在理论上 时间复杂度更胜一筹,但实际上,也要看图的稠密程度,如果 图很大且非常稠密的情况下,虽然 SPFA的时间复杂度接近Bellman_ford,但实际时间消耗 可能是 SPFA耗时更多。针对这种情况,我在后面题目讲解中,会特别加入稠密图的测试用例来给大家讲解。

拓展

这里可能有录友疑惑,while (!que.empty()) 队里里 会不会造成死循环? 例如 图中有环,这样一直有元素加入到队列里?其实有环的情况,要看它是 正权回路 还是 负权回路。题目描述中,已经说了,本题没有 负权回路 。如图:正权回路 就是有环,但环的总权值为正数。在有环且只有正权回路的情况下,即使元素重复加入队列,最后,也会因为 所有边都松弛后,节点数值(minDist数组)不在发生变化了 而终止。(而且有重复元素加入队列是正常的,多条路径到达同一个节点,节点必要要选择一个最短的路径,而这个节点就会重复加入队列进行判断,选一个最短的)在0094.城市间货物运输I 中我们讲过对所有边 最多松弛 n -1 次,就一定可以求出所有起点到所有节点的最小距离即 minDist数组。即使再松弛n次以上, 所有起点到所有节点的最小距离(minDist数组) 不会再变了。 (这里如果不理解,建议认真看0094.城市间货物运输I讲解)所以本题我们使用队列优化,有元素重复加入队列,也会因为最后 minDist数组 不会在发生变化而终止。节点再加入队列,需要有松弛的行为, 而 每个节点已经都计算出来 起点到该节点的最短路径,那么就不会有 执行这个判断条件if (minDist[to] > minDist[from] + value),从而不会有新的节点加入到队列。但如果本题有 负权回路,那情况就不一样了,我在下一题目讲解中,会重点讲解 负权回路 带来的变化。

python code1

from collections import deque
def main1():# n, m = 6, 5# edges = [[5, 6, 1],[4, 5, 1],[3, 4, 1],[2, 3, 1],[1, 2, 1]]n, m = 6, 7edges = [[5, 6, -2],[1, 2, 1],[5, 3, 1],[2, 5, 2],[2, 4, -3],[4, 6, 4],[1, 3, 5]]grid = [[] for _ in range(n+1)]for edge in edges:grid[edge[0]].append(edge[1:])start = 1   # 起点end = n     # 终点minDist = [float('Inf') for _ in range(n+1)]minDist[start] = 0que = deque()que.append(start)   # 队列里放入起点while que:node = que.popleft()for edge in grid[node]:s, t, val = node, edge[0], edge[1]if minDist[t] > minDist[s] + val:   # 开始松弛minDist[t] = minDist[s] + valque.append(t)  #  松弛过的元素加入队列print('开始松弛')print(minDist)if minDist[end] == float('Inf'):print('unconnected')  # 不能到达终点else: print(minDist[end])  # 到达终点最短路径

code python 打印记录结果

"""
n, m = 6, 5
edges = [[5, 6, 1],[4, 5, 1],[3, 4, 1],[2, 3, 1],[1, 2, 1]]
开始松弛
[inf, 0, 1, inf, inf, inf, inf]
开始松弛
[inf, 0, 1, 2, inf, inf, inf]
开始松弛
[inf, 0, 1, 2, 3, inf, inf]
开始松弛
[inf, 0, 1, 2, 3, 4, inf]
开始松弛
[inf, 0, 1, 2, 3, 4, 5]
5n, m = 6, 7
edges = [[5, 6, -2],[1, 2, 1],[5, 3, 1],[2, 5, 2],[2, 4, -3],[4, 6, 4],[1, 3, 5]]开始松弛
[inf, 0, 1, inf, inf, inf, inf]
开始松弛
[inf, 0, 1, 5, inf, inf, inf]
开始松弛
[inf, 0, 1, 5, inf, 3, inf]
开始松弛
[inf, 0, 1, 5, -2, 3, inf]
开始松弛
[inf, 0, 1, 5, -2, 3, 1]
开始松弛
[inf, 0, 1, 4, -2, 3, 1]
1
"""

code python 2

from collections import deque
def main():n,m = [int(v) for v in input().split(' ')]grid = [[] for _ in range(n+1)]for _ in range(m):v = [int(v) for v in input().split(' ')]grid[v[0]].append([v[1], v[2]])  # 邻接表  将所有边保存起来  p1 指向 p2,权值为 valstart = 1   # 起点end = n     # 终点minDist = [float('Inf') for _ in range(n+1)]minDist[start] = 0que = deque()que.append(start)   # 队列里放入起点while que:node = que.popleft()for edge in grid[node]:s, t, val = node, edge[0], edge[1]if minDist[t] > minDist[s] + val:   # 开始松弛minDist[t] = minDist[s] + valque.append(t)  #  松弛过的元素加入队列if minDist[end] == float('Inf'):print('unconnected')  # 不能到达终点else: print(minDist[end])  # 到达终点最短路径

code python 3

from collections import dequeclass Edge:# 邻接表def __init__(self, to, val):self.to = to  # 链接的节点self.val = val  # 边的权重# n, m = 6, 5
# edges = [[5, 6, 1],[4, 5, 1],[3, 4, 1],[2, 3, 1],[1, 2, 1]]n, m = 6, 7
edges = [[5, 6, -2],[1, 2, 1],[5, 3, 1],[2, 5, 2],[2, 4, -3],[4, 6, 4],[1, 3, 5]]
grid = [[] for _ in range(n+1)]
for edge in edges:grid[edge[0]].append(Edge(edge[1], edge[2]))start = 1   # 起点
end = n     # 终点minDist = [float('Inf') for _ in range(n+1)]
minDist[start] = 0que = deque()
que.append(start)   # 队列里放入起点while que:node = que.popleft()for edge in grid[node]:s, t, val = node, edge.to, edge.valif minDist[t] > minDist[s] + val:   # 开始松弛minDist[t] = minDist[s] + valque.append(t)  #  松弛过的元素加入队列print('开始松弛')print(minDist)if minDist[end] == float('Inf'):print('unconnected')  # 不能到达终点
else: print(minDist[end])  # 到达终点最短路径

相关文章:

代码随想录学习 day54 图论 Bellman_ford 队列优化算法(又名SPFA) 学习

Bellman_ford 队列优化算法&#xff08;又名SPFA&#xff09; 卡码网&#xff1a;94. 城市间货物运输 I 题目描述 某国为促进城市间经济交流&#xff0c;决定对货物运输提供补贴。共有 n 个编号为 1 到 n 的城市&#xff0c;通过道路网络连接&#xff0c;网络中的道路仅允许从…...

递归遍历树结构,前端传入一整颗树,后端处理这个树,包括生成树的id和pid等信息,

递归逻辑 递归遍历树结构&#xff0c;将树结构转换list集合 并添加到 flowStepTree 集合 // 递归遍历树结构&#xff0c;将树结构转换list集合 并添加到 flowStepTree 集合private static void settingTree(ProductFlowStepVO node, Long parentId, String ancestors, List<…...

Nginx详解(超级详细)

目录 Nginx简介 1. 为什么使用Nginx 2. 安装Nginx Nginx的核心功能 1. Nginx反向代理功能 2. Nginx的负载均衡 3 Nginx动静分离 Nginx简介 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;在BSD-like 协…...

postman使用旧版本报错version mismatch detected

卸载 postman又重装了别的版本&#xff0c;打开后遇到了这个报错&#xff0c;解决办法如下&#xff1a; 删除缓存文件 C:\Users\Administrator\AppData\Roaming\Postman 下载PostMan 提取码&#xff1a;6k51...

探索数据的隐藏维度:使用Scikit-Learn进行特征交互性预测

探索数据的隐藏维度&#xff1a;使用Scikit-Learn进行特征交互性预测 在机器学习中&#xff0c;特征交互性是指不同特征之间可能存在的复杂关系&#xff0c;这些关系对预测结果有着重要影响。Scikit-Learn&#xff08;简称sklearn&#xff09;&#xff0c;作为Python中广受欢迎…...

首个WebAgent在线评测框架和流程数据管理平台来了,GPT-4、Qwen登顶闭源和开源榜首!

在当今科技迅速发展的时代&#xff0c;大型语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;正以前所未有的速度改变着我们与数字世界的互动方式。基于LLM的智能代理&#xff08;LLM Agent&#xff09;&#xff0c;从简单的信息搜索到复杂的网页操作&…...

UE TSharedPtr

文章目录 概述TSharedPtrTSharedPtr包含2部分 构造&#xff0c;析构&#xff0c;拷贝构造&#xff0c;移动构造构造拷贝构造移动构造 小结 概述 之前写过一篇c的智能指针的&#xff0c;这篇写下ue的。本质上来说是差不多的&#xff0c;可以简单看看。 TSharedPtr 如下图&…...

基于X86+FPGA+AI的远程医疗系统,支持12/13代 Intel Core处理器

工控主板&#xff1a;支持12/13代 Intel Core处理器&#xff0c;适用于远程医疗系统 顺应数字化、网络化、智能化发展趋势&#xff0c;国内医疗产业改革正在积极推进&#xff0c;远程医疗、智慧医疗等新模式新业态创新发展和应用&#xff0c;市场空间不断扩大&#xff0c;而基…...

微信小程序开发入门指南

文章目录 一、微信小程序简介二、微信小程序开发准备三、微信小程序开发框架四、微信小程序开发实例六、微信小程序开发进阶6.1 组件化开发6.2 API调用6.3 云开发 七、微信小程序开发注意事项7.1 遵守规范7.2 注意性能7.3 保护用户隐私 八、总结 大家好&#xff0c;今天将为大家…...

一个非常好的美图展示网站整站打包源码,集成了wordpress和开源版ripro主题,可以完美运营。

一个非常好的美图展示网站整站打包源码&#xff0c;集成了wordpress和开源版ripro主题&#xff0c;可以完美运营。 自带了5个多g的美图资源&#xff0c;让网站内容看起来非常大气丰富&#xff0c;可以快速投入运营。 这个代码包&#xff0c;原网站已经稳定运营多年&#xff0…...

MySQL:mysql的数据类型

MySQL 作为一个流行的关系型数据库管理系统&#xff0c;支持多种数据类型以满足不同的数据处理和存储需求。正确理解和使用这些数据类型对于提高数据库性能、确保数据完整性和准确性至关重要。 MySQL 数据类型 数据类型定义了列中可以存储什么数据以及该数据怎样存储的规则。…...

IPython魔法命令的深入应用

目录 IPython魔法命令的深入应用 一、魔法命令基础 1. 魔法命令的分类 2. 基本使用 二、高级应用技巧 1. 数据交互与处理 2. 交互式编程与调试 三、魔法命令的进阶操作 1. 自定义魔法命令 2. 利用魔法命令优化工作流程 四、总结与展望 IPython魔法命令的深入应用 IP…...

Yum包下载

1. 起因 内网有一台服务器需要升级php版本,维护的同学又不想二进制安装.服务器只有一个光盘的yum仓库 2. 解决方法 解决思路如下: 外网找一台机器配置php8.3.8的仓库外网服务器下载软件集并打包内网服务器上传并解压实现升级 2.1 下载php8.3.8仓库 配置php仓库 rootcent…...

数据结构代码

文章目录 线性表的插入线性表的删除单链表的建立栈的顺序存储队列的顺序存储串的顺序存储树的存储二叉树遍历前序遍历中序遍历后序遍历 二分法插入排序利用普里姆算法构造最小生成树 线性表的插入 #a: 列表&#xff0c;pos: 要插入的位置&#xff0c;key: 要插入的数据&#x…...

环信IM x 亚马逊云科技,助力出海企业实现可靠通讯服务

随着全球化进程的加速&#xff0c;越来越多的企业选择出海&#xff0c;拓展国际市场。然而&#xff0c;面对不同国家和地区的用户&#xff0c;企业在即时通讯方面遇到了诸多挑战。为了帮助企业克服这些困难&#xff0c;环信IM与亚马逊云科技强强联手&#xff0c;共同推出了一套…...

R语言画散点图-饼图-折线图-柱状图-箱线图-直方图-等高线图-曲线图-热力图-雷达图-韦恩图(二D)

R语言画散点图-饼图-折线图-柱状图-箱线图-直方图-等高线图-曲线图-热力图-雷达图-韦恩图&#xff08;二D&#xff09; 散点图示例解析效果 饼图示例解析效果 折线图示例解析效果 柱状图示例解析效果 箱线图示例解析效果 直方图示例解析效果 等高线图使用filled.contour函数示例…...

go中map

文章目录 Map简介哈希表与Map的概念Go语言内建的Map类型Map的声明Map的初始化Map的访问Map的添加和修改Map的删除Map的遍历 Map的基本使用Map的声明与初始化Map的访问与操作Map的删除Map的遍历Map的并发问题实现线程安全的Map 3. Map的访问与操作3.1 访问Map元素代码示例&#…...

02-用户画像-技术架构+业务划分

技术架构 python开发 es flume 流数据读取写入kafka文件 kafka 消息队列 sqoop 将数据导入数仓hive StructureStream 动态画像的处理 SparkSQL 静态画像的处理 &#xff0c;批数据处理 读取kafka获取用户行为数据 fineBI 数据展示 业务划分 离线业务 静态画像 …...

HarmonyOS应用开发者高级认证,Next版本发布后最新题库 - 单选题序号1

本来打算找到工作再整理高级的题库&#xff0c;但一直没什么面试机会。宅在家里也不知道干些什么。索性就把高级的题库整理出来了。也算有头有尾。高级的题库更新之后&#xff0c;专业性更强了&#xff0c;不是真正从事这一行的&#xff0c;很难做出来。本人就是个小菜鸡&#…...

敲详细的springboot中使用RabbitMQ的源码解析

这里介绍的源码主要是涉及springboot框架下的rabbitmq客户端代码&#xff08;具体在springframework.amqp.rabbit包下&#xff0c;区分一下不由springboot直接接管的spring-rabbit的内容&#xff09;&#xff0c;springboot基于RabbitMQ的Java客户端建立了简便易用的框架。 sp…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

pycharm 设置环境出错

pycharm 设置环境出错 pycharm 新建项目&#xff0c;设置虚拟环境&#xff0c;出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)

第一篇&#xff1a;Liunx环境下搭建PaddlePaddle 3.0基础环境&#xff08;Liunx Centos8.5安装Python3.10pip3.10&#xff09; 一&#xff1a;前言二&#xff1a;安装编译依赖二&#xff1a;安装Python3.10三&#xff1a;安装PIP3.10四&#xff1a;安装Paddlepaddle基础框架4.1…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...