最短路算法

news2025/1/9 17:11:56

文章目录



最短路总览

最短路


朴素Dijkstra - 稠密图 - O ( n 2 ) O(n^2) O(n2)

具体思路

  • 我们需要三个数组,分别是记录边的g[][]、记录到 1 1 1 节点距离的dist[]、还有标记节点是否已经求得最短路的st[]
  • 将距离数组初始化为 I N F INF INF ,然后添加第一个最短距离:dist[1] = 0,意思就是 1 1 1 节点到 1 1 1 节点的最短距离是 0 0 0
  • 寻找没有确定最短距离的节点中距离最短的那个点
    • 将这个点的距离标记为已经求得最短距离了(因为是所有未确定中最小的)
    • 用这个点的所有边去更新其连接的其他节点
  • 重复上一步,一轮能确定一个点的最短路,重复 n n n 轮就能将所有点的最短路找到
  • 当然也可以在中间加个优化:如果第 n n n 个点的最短路已经确定,那就直接退出返回即可

时间复杂度分析

重复 n n n 轮,每轮遍历所有节点找最小值,然后遍历所有边,所以是 O ( n ∗ ( n + n ) ) O(n * (n + n)) O(n(n+n)),也就是 O ( n 2 ) O(n^2) O(n2)


使用场景

  • 稠密图尽量使用朴素 D i j k s t r a Dijkstra Dijkstra
    • 稠密图: m ≈ n 2 m ≈ n^2 mn2
    • 稠密图用邻接矩阵
  • 因为时间复杂度: O ( n 2 ) < O ( n 2 ⋅ l o g n ) O(n^2) < O(n^2·logn) O(n2)<O(n2logn) ,朴素比堆优化快

AcWing 849. Dijkstra求最短路 I

题目链接:https://www.acwing.com/activity/content/problem/content/918/

Dijkstra1

CODE
#include <iostream>     // 用于输入和输出
#include <cstring>      // 用于处理字符串
#include <algorithm>    // 用于算法操作

using namespace std;

const int N = 520;      // 定义常量N
int n, m;               // 定义整型变量n和m
int g[N][N];            // 定义二维数组g
int dist[N];            // 定义一维数组dist
bool st[N];             // 定义布尔数组st

int dijkstra(){         // 定义dijkstra函数
    memset(dist, 0x3f, sizeof dist);  // 初始化dist数组
    dist[1] = 0;        // 设置dist数组的第一个元素为0

    for(int i = 1; i <= n; ++i){  // 遍历n个节点
        int t = -1;
        for(int j = 1; j <= n; ++j)  // 寻找未被访问的距离最小的节点
            if(!st[j] && (t == -1 || dist[j] < dist[t]))
                t = j;

        st[t] = true;   // 标记节点t已被访问

        for(int j = 1; j <= n; ++j)  // 更新所有节点到源点的距离
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }

    // 如果dist[n]的值未改变,返回-1,否则返回dist[n]
    return dist[n] == 0x3f3f3f3f ? -1 : dist[n];
}

int main()  // 主函数
{
    cin >> n >> m;  // 输入n和m
    memset(g, 0x3f, sizeof g);  // 初始化g数组

    int a, b, c;
    while (m -- ){  // 输入m条边
        scanf("%d%d%d", &a, &b, &c);
        g[a][b] = min(g[a][b], c);  // 更新边的权值
    }

    int t = dijkstra();  // 调用dijkstra函数

    cout << t << endl;  // 输出结果
}



堆优化 D i j k s t r a Dijkstra Dijkstra 算法 - 稀疏图 - O ( m l o g n ) O(mlogn) O(mlogn)

我们可以发现,朴素 D j i k s t r a Djikstra Djikstra 一共分为三步:

  • 遍历所有节点
    • 找出最小路径的节点
    • 由这个节点更新其他节点的距离

其中最后两步:找出最小和更新距离可以用我们学过的一个数据结构 - 来优化


具体思路和时间复杂度分析

  • 其他地方不变,将更新过的节点用堆来储存,这样就可以将查询时间从 O ( n ) O(n) O(n) 降到 O ( 1 ) O(1) O(1),也就是说不用再遍历数组了
  • 每次弹出一个元素对其他值进行修改,复杂度就是 O ( m ⋅ l o g n ) O(m · logn) O(mlogn)
    • 这个地方其实分手写堆还是 S T L STL STL
      • 手写堆:我们自己能保证堆中只有 n n n 个元素,弹出后修改某一元素的值。那么弹出元素全部修改一遍需要 O ( l o g n ) O(logn) O(logn) ,而排空堆一共需要 m m m 次,所以一共是 O ( m ⋅ l o g n ) O(m·logn) O(mlogn)
      • S T L STL STL:我们每次更新了一个节点的值就将这个值入堆,所以说堆中一共会有 m m m 个元素,那么等全部循环完就是 O ( m ⋅ l o g m ) O(m·logm) O(mlogm)
    • 在最坏情况的稠密图中, S T L STL STL 堆复杂度是 O ( m ⋅ l o g m ) O(m·logm) O(mlogm) ,也就是 O ( n 2 ⋅ l o g ( n 2 ) ) O(n^2·log(n^2)) O(n2log(n2)) ,化简得 O ( 2 n 2 ⋅ l o g n ) O(2n^2·logn) O(2n2logn) ,这个复杂度跟手写堆的 O ( n 2 ⋅ l o g n ) O(n^2·logn) O(n2logn) 差不多,所以我们用优先队列
  • 结论就是,复杂度为: O ( m ⋅ l o g n ) O(m·logn) O(mlogn)

使用场景

  • 适用于稀疏图
    • 稀疏图: m ≈ n m ≈ n mn
    • 稀疏图用邻接表存
  • 因为时间复杂度 O ( m l o g n ) O(mlogn) O(mlogn) 比朴素版 O ( n 2 ) O(n^2) O(n2) 低:

AcWing 850. Dijkstra求最短路 II

题目链接:https://www.acwing.com/activity/content/problem/content/919/

Dijkstra2

CODE
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair<int, int> pii;

const int N = 1e6 + 10;
int h[N], e[N], ne[N], w[N], idx;
int dist[N];
bool st[N];
int n, m;
int a, b, c;

void add(int a, int b, int c){
    e[idx] = b;
    ne[idx] = h[a];
    w[idx] = c;
    h[a] = idx++;
}

int dijkstra(){
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    priority_queue<pii, vector<pii>, greater<pii>> heap;
    heap.push({0, 1});
    
    while(heap.size()){
        auto t = heap.top();
        heap.pop();
        
        int ver = t.second, distance = t.first;
        if(st[ver]) continue;
        
        st[ver] = true;
        
        for(int i = h[ver]; i != -1; i = ne[i]){
            int j = e[i];
            if(dist[j] > dist[ver] + w[i]){
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
    
    return dist[n] == 0x3f3f3f3f ? -1 : dist[n];
}

int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    
    while (m -- ){
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    
    cout << dijkstra() << endl;
}


D i j k s t r a Dijkstra Dijkstra 算法的局限

  • D i j k s t r a Dijkstra Dijkstra 算法没办法处理负权图,为什么呢?
    1
    Dijkstra缺陷

    • 素材来自:https://www.acwing.com/solution/content/6320/ 的评论区
      什么?原来是评论区大神(ΩДΩ)!!!orz %%%%%%
  • 总结来说,就是 D i j k s t r a Dijkstra Dijkstra 算法采用了贪心思想,所以出错,原因如下:

    • 每次取最小的值为基准,更新其他值,然后这个点被打上标记,不能在用来更新其他值,但是它的值可以被更新。
    • 如果说存在负权边,那么我之前打上标记的节点的值可能就不是最短路的值了,虽然这个点的dist[]值可以被更新,但是要想再用正确的最短路的值更新其他节点就做不到了(因为被打上标记了),所以最后的答案是可能是错的。
  • 它们一刻也没有为 D i j k s t r a Dijkstra Dijkstra 算法而哀悼,立刻赶来战场的是 — B e l l m a n _ f o r d Bellman\_ford Bellman_ford 算法和 S P F A SPFA SPFA 算法!!!



Bellman - Ford 算法 - 随便存边 - O ( n m ) O(nm) O(nm)

具体思路

bellmanford

  • 首先,循环 k k k 次(题目指定最大次数,没指定就是节点数):
    • 每次循环遍历所有边,更新可以更新的边,俗称松弛操作
  • 其次,没有了,就这么多,是的,就这么多。
  • 所有操作做完之后可以保证公式: d i s t [ b ] ≤ d i s t [ a ] + w dist[b] ≤ dist[a] + w dist[b]dist[a]+w俗称三角不等式
    • 为什么强调 B e l l m a n − f o r d Bellman-ford Bellmanford 满足这个公式呢?
      因为 D i j k s t r a Dijkstra Dijkstra 并不满足(有负权边),之前说过 D i j k s t r a Dijkstra Dijkstra 的缺陷,这就导致了如果存在负权边时,有些节点的值并不是真正的最短路,也就不满足以上公式了。
  • 由于满足这个公式,所以以上操作做完,求得的所有点的值都是 k k k 次操作内的最短路了。

时间复杂度分析

两遍循环,一重循环循环 n n n 次,每次循环都遍历每条边,把能更新的都更新一遍,那么就是 O ( n m ) O(nm) O(nm)


使用场景

  • 有负权的图
    • 但是不能有负环,有负环的话就会在负环上无线绕,得到的最短路就是负无穷-INF
  • 对操作数有限制的题
    • 有些题目会对走的次数限制在 k k k 次,那么我们就在外围循环循环 k k k 次而不是 n n n 次。
      也就是最多不经过 k k k 条边的意思。
    • 如果没有限制,那就循环 n n n 次,把所有点都轮一遍。但是一般情况下都会用之后说的 S P F A SPFA SPFA 算法。
  • 带负环的图其实也可以做,当我们进行完所有松弛操作后,所有节点的值都满足三角不等式,这个时候我们再进行一次松弛操作,如果检测出来还有能操作的点,那么一定存在负环。
    • y总说的是:走了 n n n 次,那么就一定有 n + 1 n + 1 n+1 个节点,而我们一共也就 n n n 个点,由抽屉原理得一定存在负环。
      这里应该说的是证明,但是判负环基本不用 B e l l m a n − f o r d Bellman-ford Bellmanford 来做,而是用 S P F A SPFA SPFA 算法。
    • 本题的边可以用任意方式存,只要能被遍历到即可,所以直接拿结构体数组存了。


AcWing 853. 有边数限制的最短路

题目链接:https://www.acwing.com/activity/content/problem/content/922/。

bellmanford题目

CODE
#include <iostream>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f

using namespace std;

const int N = 510, M = 10010;

struct{
    int a, b, c;
}edges[M];

int n, m, k;
int a, b, c;
int dist[N], backup[N];

void bellman_ford(){
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    for(int i = 0; i < k; ++i){
        memcpy(backup, dist, sizeof dist);
        for(int j = 0; j < m; ++j){
            auto e = edges[j];
            dist[e.b] = min(dist[e.b], backup[e.a] == INF ? INF : backup[e.a] + e.c);
        }
    }
}

int main()
{
    cin >> n >> m >> k;
    for(int i = 0; i < m; ++i){
        scanf("%d%d%d", &a, &b, &c);
        edges[i] = {a, b, c};
    }
    
    bellman_ford();
    
    if(dist[n] == INF) puts("impossible");
    else printf("%d\n", dist[n]);
}
代码疑问点解析
  • backup[]数组:
    • 备份数组,用于备份上一次更新时所有最短路的值。
    • 为什么要备份?
      • 在一次外重循环中,会对所有的边进行遍历,把能更新的更新了,但是这样就会有个问题,我先更新的值可能会对后面的更新产生影响。
        比如有一条路 A − B − C A - B - C ABC , A A A 有最短路,而 B , C B, C B,C I N F INF INF ,没有最短路,题目给定只许进行一次操作。很显然,只走一步的话 C C C 是不可能有最短路的,但是错误发生了:先遍历 A − B A - B AB 边, B B B 获得最短路,那么到这应该结束了,但是循环内会把所有边都遍历一遍,如果没有备份数组,那么 C C C 就会由 B B B 而获得最短路。
        我们一次外层循环想得到的结果是根据已经有最短路的节点去更新没有最短路的节点,而且仅仅只走一步,当没有备份时,我们可能会向外发散很多步
  •   dist[e.b] = min(dist[e.b], backup[e.a] == INF ? INF : backup[e.a] + e.c);
    
    • 这步操作的意思是:
      • 如果有一条边 A − B A - B AB ,边权为负数,比方说为 − s -s s,且两个都没最短路,那么更新的时候只用min()函数比较更新前后的值的时候就会把 B B B 的最短路更新为 I N F − s INF - s INFs ,但是其实 B B B 依然没有最短路,对于终点情况也是一样。
      • 如果只写一个裸的min()函数,不进行判断的话,需要在最后判断是否有最短路的时候把判断改为
        if (dist[n] > 0x3f3f3f3f / 2) puts("impossible");
        
        只要大于一个不可能的数就判断为没有最短路。


S P F A SPFA SPFA 算法 - 一般 O ( n ) O(n) O(n),最坏 O ( n m ) O(nm) O(nm)

有两个应用

  • 求最短路
  • 判负环

具体思路 - 求最短路

B e l l m a n − f o r d Bellman-ford Bellmanford 算法优化一下,每次不将所有边都遍历一遍,而是将更新后的节点入队,每次从队列里面拿节点进行更新。


时间复杂度分析

  • 从第一个节点开始入队,最好的情况就是每个节点只需要更新一次,那么就是 O ( n ) O(n) O(n)
  • 最坏的情况是:
    spfa

AcWing 851. spfa求最短路

题目链接:https://www.acwing.com/activity/content/problem/content/920/。

CODE
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 0x3f3f3f3f

using namespace std;

const int N = 1e5 + 10;
int h[N], e[N], ne[N], w[N], idx;
int n, m;
int a, b, c;
bool st[N];
int dist[N];

void add(int a, int b, int c){
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

int spfa(){
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    queue<int> q;
    q.push(1);
    st[1] = true;
    
    while(q.size()){
        auto t = q.front();
        q.pop();
        st[t] = false;
        
        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            
            if(dist[j] > dist[t] + w[i]){       // 这一步判断必须加上,防止无限入队导致TLE
                dist[j] = dist[t] + w[i];
                if(!st[j]){
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
    
    return dist[n];
}

int main()
{
    memset(h, -1, sizeof h);
    
    cin >> n >> m;
    
    while (m -- ){
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    
    int ans = spfa();
    
    if(ans == INF) puts("impossible");
    else printf("%d\n", ans);
}
代码细节
  • st[]数组:用来标记队列中的节点,已经入队了就没必要再次入队了,防止无限入队。
  • if判断是否更新而不是直接用min()函数:防止无限入队。

具体思路 - 判负环

维护一个cnt[]数组,每当某节点被更新一次就在源点对应的记录数组cnt[]+1,当某个记录数突破了节点数时,肯定存在负环,证明详情见 B e l l m a n − f o r d Bellman-ford Bellmanford 算法y总原话之抽屉原理


AcWing 852. spfa判断负环

题目链接:https://www.acwing.com/activity/content/problem/content/921/。

spfa判负环

CODE
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 2010, M = 10010;
int n, m;
int a, b, c;
int h[N], e[M], ne[M], w[M], idx;
int dist[N], cnt[N];
bool st[N];

void add(int a, int b, int c){
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

bool spfa(){
    //memset(dist, 0x3f, sizeof dist);	加不加都行
    //dist[1] = 0;
    
    queue<int> q;
    for(int i  = 1; i <= n; ++i){
        q.push(i);
        st[i] = true;
    }
    
    while(q.size()){
        int t = q.front();
        q.pop();
        st[t] = false;
        
        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            
            if(dist[j] > dist[t] + w[i]){
                dist[j] = dist[t] + w[i];
                cnt[j] = cnt[t] + 1;
                
                if(!st[j]){
                    q.push(j);
                    st[j] = true;
                }
                
                if(cnt[j] >= n) return true;
            }
        }
    }
    
    return false;
}

int main()
{
    memset(h, -1, sizeof h);
    
    cin >> n >> m;
    while (m -- ){
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    
    if(spfa()) puts("Yes");
    else puts("No");
}
代码疑点解读
  • 为什么一开始把所有点入队:
    • 因为这样可以检测到所有边上的负环,而不是仅仅只有最短路上的负环了。
      全部入队
      素材来自:https://www.acwing.com/solution/content/6336/评论区。
      什么?又是评论区大神?(ΩДΩ) orz %%%%%
  • 为什么dist[]不用初始化:
    • 因为如果边权为正数,dist[]永远不会更新,直到遇见了负数才会更新,如果有负环那就会一直更新直到爆 n n n 返回false


F l o y d Floyd Floyd 算法 - O ( n 3 ) O(n^3) O(n3)

思路简介

采用了动态规划思想,具体怎样我也不知道 >_<,没学过呜呜呜。
总之很短很暴力。
别问,问就是背过

菜就多练,学不会就背过。
暴力是暴力, F l o y d Floyd Floyd F l o y d Floyd Floyd
你要是一直拿 F l o y d Floyd Floyd 当暴力。
你咋不去自己写一个?


时间复杂度分析

三重循环所以是—— O ( n 3 ) O(n^3) O(n3)
太美丽了家人们。


AcWing 854. Floyd求最短路

题目链接:https://www.acwing.com/activity/content/problem/content/923/。

floyd

#include <iostream>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f

using namespace std;

int n, m, k;
const int N = 210, M = 20010;
int d[N][N];

void floyd(){
    for(int k = 1; k <= n; ++k)
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                d[i][j] = min(d[i][j], 
                	(d[i][k] == INF || d[k][j] == INF) ? INF : d[i][k] + d[k][j]);
                
                // y总写的d[i][j] = min(d[i][j], d[i][k] + d[k][j]);              
}

int main()
{
    cin >> n >> m >> k;
    
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            if(i == j) d[i][j] = 0;
            else d[i][j] = INF;
            
    while (m -- ){
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        d[a][b] = min(d[a][b], c);
    }
    
    floyd();
    
    while(k--){
        int a, b;
        scanf("%d%d", &a, &b);
        
        if(d[a][b] == INF) puts("impossible");
        else printf("%d\n", d[a][b]);
    }
}
代码疑点解读
  • 为什么跟y总不一样的地方能过,什么思路?
    • 这个跟 B e l l m a n − f o r d Bellman-ford Bellmanford 一样,把所有边轮了一遍,所以会出现之前说的INF - k的情况出现,所以加了个判断。
    • 至于为什么这么写,我只能说我是仿照 B e l l m a n − f o r d Bellman-ford Bellmanford 写的判断,但是只判断前一个或后一个都会 WA,但是一起判断了就AC了,所以我就这么写了,原理我也不懂,嘿嘿。
  • 为什么初始化的时候把每个自己到自己的节点距离设为 0 0 0
    源点初始化
    • 素材来源:https://www.acwing.com/activity/content/code/content/48531/评论区。
      什么?又双叒叕是评论区大神???!!!(ΩДΩ) orz %%%%

写了一天总算写完了,真的很复杂啊 %%%%%%%%%%%%%%

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

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

相关文章

九章量子计算机:引领量子计算的新篇章

九章量子计算机:引领量子计算的新篇章 一、引言 随着科技的飞速发展,量子计算已成为全球科研领域的前沿议题。九章量子计算机作为中国自主研发的量子计算机,具有划时代的意义。本文将深入探讨九章量子计算机的原理、技术特点、应用前景等方面,带领读者领略量子计算的魅力…

11.28~11.29基本二叉树的性质、定义、复习;排序算法;堆

完全二叉树&#xff08;Complete Binary Tree&#xff09;是一种特殊的二叉树结构&#xff0c;它具有以下特点&#xff1a; 所有的叶子节点都集中在树的最后两层&#xff1b;最后一层的叶子节点都靠左排列&#xff1b;除了最后一层&#xff0c;其他层的节点数都达到最大值。 …

短剧行业@2023:狂飙、刹车与新生

【潮汐商业评论/原创】 “豪门复仇”“先婚后爱”“重生”“穿越”&#xff0c;Ashley几乎每次回家路过保安亭&#xff0c;都能看到大叔在看这类上头小短剧&#xff0c;就连有时候在公司&#xff0c;也能听到保洁阿姨在看类似的视频。 久而久之&#xff0c;从好奇到“入坑&am…

利用ElementUI配置商品的规格参数

商品有不同的规格组合&#xff0c;自动生成对应规格的所有组合&#xff0c;并设置该规格的图片、价格、库存数据。 <template><div class"sku-list"><template v-if"!disabled"><div class"sku-list-head"><el-but…

Zigbee—基于Z-STACK组网

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;チノカテ—ヨルシカ 0:46━━━━━━️&#x1f49f;──────── 4:08 &#x1f504; ◀️ ⏸ ▶️ ☰ &a…

nginx配置反向代理及负载均衡

目录 1.前端发送的请求&#xff0c;是如何请求到后端服务的1.nginx 反向代理的好处&#xff1a;2.nginx 反向代理的配置方式&#xff1a;3. nginx 负载均衡的配置方式 1.前端发送的请求&#xff0c;是如何请求到后端服务的 1.nginx 反向代理的好处&#xff1a; 提高访问速度 因…

如何使用 NFTScan NFT API 在 Starknet 网络上开发 Web3 应用

Starknet 是由以色列软件公司 StarkWare 开发的免许可的第 2 层网络。Starknet 作为以太坊上的 ZK Rollup 运行&#xff0c;帮助 dApp 使用 STARK 证明以更低的交易成本实现更大的计算规模。该网络允许智能合约与区块链上部署的其他合约进行交互&#xff0c;从而提高协议之间的…

大数据Doris(三十一):Doris简单查询

文章目录 Doris简单查询 一、简单查询 二、​​​​​​​Join

基于Springboot的在线问卷调查系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的在线问卷调查系统(有报告)。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring…

golang WaitGroup的使用与底层实现

使用的go版本为 go1.21.2 首先我们写一个简单的WaitGroup的使用代码 package mainimport ("fmt""sync" )func main() {var wg sync.WaitGroupwg.Add(1)go func() {defer wg.Done()fmt.Println("xiaochuan")}()wg.Wait() }WaitGroup的基本使用场…

Peter算法小课堂—差分与前缀和

差分 Codeforces802 D2C C代码详解 差分_哔哩哔哩_bilibili 一维差分 差分与前缀和可以说成减法和加法的关系、除法和乘法的关系、积分和微分的关系&#xff08;听不懂吧&#xff09; 给定数组A&#xff0c;S为A的前缀和数组&#xff0c;则A为S的差分数组 差分数组构造 现…

Unittest(1):unittest单元测试框架简介setup前置初始化和teardown后置操作

unittest单元测试框架简介 unittest是python内置的单元测试框架&#xff0c;具备编写用例、组 织用例、执行用例、功能&#xff0c;可以结合selenium进行UI自动化测 试&#xff0c;也可以结合appium、requests等模块做其它自动化测试 官方文档&#xff1a;https://docs.pytho…

opencv 图像边框

cv.copyMakeBorder() 图像设置边框或者填充

HarmonyOs 4 (一) 认识HarmonyOs

目录 一 HarmonyOs 背景1.1 发展时间线1.2 背景分析1.2.1 新场景1.2.2 新挑战1.2.3 鸿蒙生态迎接挑战 二 HarmonyOS简介2.1 OpenHarmony2.2 HarmonyOS Connect2.3 HarmonyOS Next**2.4 ArkTS &#xff08;重点掌握&#xff09;****2.5 ArkUI** 三 鸿蒙生态应用核心技术理念**3.…

c/c++概念辨析-指针常量常量指针、指针函数函数指针、指针数组数组指针

概念澄清&#xff1a; 统一规则&#xff1a; 不管是XX指针&#xff0c;还是指针XX&#xff0c;后者是本体&#xff0c;前者只是个定语&#xff0c;前者也可以替换为其他同类&#xff08;例如字符串&#xff09;&#xff0c;帮助理解。 XX指针&#xff1a; 可简单理解为&#…

骨传导耳机是智商税吗?骨传导耳机是利用什么原理听歌?

骨传导耳机并非智商税&#xff0c;而是一种新兴的技术产品。作为是一种新型的听音设备&#xff0c;它采用了与传统耳机不同的工作原理&#xff0c;通过将声音通过骨骼传导到内耳&#xff0c;实现了不用堵塞耳道就能听到声音的效果。相比传统耳机&#xff0c;骨传导耳机具有一些…

mac本地部署stable-diffusion

下载Homebrew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" ①输入“1”选择中科大版本&#xff0c;然后输入Y(YES)&#xff0c;直接输入开机密码&#xff08;不显示&#xff09;然后回车确认&#xff0c;开始下载 ②…

matlab 基于卡尔曼滤波的GPS-INS的数据融合的导航

1、内容简介 略 25-可以交流、咨询、答疑 2、内容说明 基于卡尔曼滤波的GPS-INS的数据融合的导航 "基于卡尔曼滤波的GPS-INS的数据融合的导航 基于卡尔曼滤波实现GPS-INS组合导航系统" 卡尔曼滤波、GPS、INS、数据融合、导航 3、仿真分析 4、参考论文 略 …

Linux基本指令(后篇)

目录 14.时间指令date 15.Cal指令 16.find指令(非常重要) 17.grep指令 18.打包压缩指令zip和tar以及解压指令unzip和tar 14.时间指令date date(显示当前时间) 1.在显示方面&#xff0c;使用者可以设定欲显示的格式&#xff0c;格式设定为一个加号后接数个标记&#xff0c;其中…

带头结点的双向循环链表

目录 带头结点的双向循环链表 1.存储定义 2.结点的创建 3.结点的初始化 4.尾插结点 5.尾删结点 6.头插结点 7.头删结点 8.查找并返回结点 9.在pos结点前插入结点 10.删除pos结点 11.打印链表 12.销毁链表 13.头插结点2.0版 14.尾插结点2.0版 前言&#xff1a; 当…