【算法基础:搜索与图论】3.4 求最短路算法(Dijkstrabellman-fordspfaFloyd)

文章目录

  • 求最短路算法总览
  • Dijkstra
    • 朴素 Dijkstra 算法(⭐原理讲解!⭐重要!)(用于稠密图)
      • 例题:849. Dijkstra求最短路 I
        • 代码1——使用邻接表
        • 代码2——使用邻接矩阵
      • 补充:稠密图和稀疏图 & 邻接矩阵和邻接表
    • 堆优化版Dijkstra算法(⭐原理讲解!⭐重要!)用于稀疏图
      • 例题:850. Dijkstra求最短路 II
  • bellman-ford
    • 例题:853. 有边数限制的最短路
      • 为什么需要对 dis 数组进行备份?
  • spfa算法(bellman-ford 算法的优化)
    • 例题:851. spfa求最短路
    • 例题:852. spfa判断负环
  • Floyd(很暴力的三重循环)
    • 例题:854. Floyd求最短路

求最短路算法总览

关于最短路可见:https://oi-wiki.org/graph/shortest-path/
在这里插入图片描述

无向图 是一种 特殊的 有向图。(所以上面的知识地图上没有区分边有向还是无向)

关于存储:稠密图用邻接矩阵,稀疏图用邻接表。
朴素Dijkstra 和 堆优化Dijkstra算法的 选择就在于图 是 稠密的还是稀疏的。

Dijkstra

朴素 Dijkstra 算法(⭐原理讲解!⭐重要!)(用于稠密图)

算法步骤:

有一个集合 s 存储当前已经确定是最短距离的点。

  1. 初始化距离,dis[1] = 0, dis[i] = +∞
  2. for i: 1 ~ n 。 (每次循环确定一个点到起点的最短距离,这样 n 次循环就可以确定 n 个点的最短距离)
    找到不在 s 中的 距离最近的点 t,将其放入 s 中。
    用 t 来更新其它所有点的距离(检查所有从 t 出发可以到达的点 x,是否有 dis[x] > dis[t] + w)

在这里插入图片描述

例题:849. Dijkstra求最短路 I

https://www.acwing.com/activity/content/problem/content/918/
在这里插入图片描述

注意图是有向图,图中可能存在重边和自环,所有边权为正值。
求从 1 号点到 n 号点 的最短距离。

按照朴素 Dijkstra 算法的原理,每次用当前不在 s 中的最短距离节点 t 更新其它所有 t 可以到达的下一个节点,重复这个过程 n 次就可以确定 n 个节点的最短距离。

代码1——使用邻接表

import java.util.*;public class Main {public static void main(String[] args){Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(), m = scanner.nextInt();// 建图List<int[]>[] g = new ArrayList[n + 1];Arrays.setAll(g, e -> new ArrayList<>());for (int i = 0; i < m; ++i) {int x = scanner.nextInt(), y = scanner.nextInt(), z = scanner.nextInt();g[x].add(new int[]{y, z});}// 初始化距离int[] dis = new int[n + 1];Arrays.fill(dis, Integer.MAX_VALUE);dis[1] = 0;boolean[] st = new boolean[n + 1];for (int i = 1; i < n; ++i) {int t = -1;// 找到当前不在 s 中的最短距离 t 的位置for (int j = 1; j <= n; ++j) {if (!st[j] && (t == -1 || dis[j] < dis[t])) t = j;}if (t == n) break;      // 当前离得最近的就是 n 了,直接返回st[t] = true;// 使用 t 更新所有从 t 出发可以达到的下一个节点for (int[] y: g[t]) dis[y[0]] = Math.min(dis[y[0]], dis[t] + y[1]);}if (dis[n] == Integer.MAX_VALUE) System.out.println("-1");else System.out.println(dis[n]);}
}

代码2——使用邻接矩阵

从题目中可以看出是稠密图,所以使用邻接矩阵效率会更高一些。

import java.util.*;public class Main {public static void main(String[] args){Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(), m = scanner.nextInt();// 建图  g[i][j]表示从i到j的距离int[][] g = new int[n + 1][n + 1];for (int[] ints : g) Arrays.fill(ints, 0x3f3f3f3f);for (int i = 0; i < m; ++i) {int x = scanner.nextInt(), y = scanner.nextInt(), z = scanner.nextInt();g[x][y] = Math.min(g[x][y], z);}// 初始化各个点到起始点的距离int[] dis = new int[n + 1];Arrays.fill(dis, Integer.MAX_VALUE);dis[1] = 0;boolean[] st = new boolean[n + 1];for (int i = 1; i < n; ++i) {int t = -1;// 找到当前不在 s 中的最短距离 t 的位置for (int j = 1; j <= n; ++j) {if (!st[j] && (t == -1 || dis[j] < dis[t])) t = j;}if (t == n) break;      // 当前离得最近的就是 n 了,直接返回st[t] = true;// 使用 t 更新所有从 t 出发可以达到的下一个节点for (int j = 1; j <= n; ++j) {dis[j] = Math.min(dis[j], dis[t] + g[t][j]);}}if (dis[n] == 0x3f3f3f3f) System.out.println("-1");else System.out.println(dis[n]);}
}

补充:稠密图和稀疏图 & 邻接矩阵和邻接表

在这里插入图片描述
总结一下:

邻接矩阵的空间复杂度为 O ( n 2 ) O(n^2) O(n2),邻接表的空间复杂度为 O ( n + m ) O(n + m) O(n+m),其中 n 是图中节点的数量,m 是边的数量。

Q:如何判断什么时候是稠密的?
A:当 m m m 接近最大可能边数 n ∗ ( n − 1 ) / 2 n * (n - 1)/2 n(n1)/2 时,那么图通常被视为稠密的。

堆优化版Dijkstra算法(⭐原理讲解!⭐重要!)用于稀疏图

如果是一个稀疏图, O ( n 2 ) O(n^2) O(n2) 的朴素 Dijkstra 算法可能会很慢,因此出现了堆优化版本的 Dijkstra 算法。
在这里插入图片描述

用堆来存储所有点到起点的最短距离,就可以减小整个算法的时间复杂度。

用 t 更新其它点的距离,因为有 m 条边,所以这个操作是 m 次,每次的时间复杂度是 logn,因此一共是 m ∗ log ⁡ n m*\log{n} mlogn。 (所以 m 比较小时,即稀疏图,使用堆优化效果更好)

其实就是用堆来优化了每次找当前和起始点最近的点的过程。(朴素的需要枚举 n)

例题:850. Dijkstra求最短路 II

https://www.acwing.com/activity/content/problem/content/919/

在这里插入图片描述

import java.util.*;public class Main {public static void main(String[] args){Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(), m = scanner.nextInt();// 建图List<int[]>[] g = new ArrayList[n + 1];Arrays.setAll(g, e -> new ArrayList<int[]>());for (int i = 0; i < m; ++i) {int x = scanner.nextInt(), y = scanner.nextInt(), z = scanner.nextInt();g[x].add(new int[]{y, z});}//int[] dis = new int[n + 1];Arrays.fill(dis, 0x3f3f3f3f);dis[1] = 0;boolean[] st = new boolean[n + 1];// 按照各个节点与初始节点之间距离 从小到大 排序PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);pq.offer(new int[]{1, 0});while (!pq.isEmpty()) {int[] cur = pq.poll();int x = cur[0], d = cur[1];if (st[x]) continue;                // 检查这个节点是否已经用来更新过了st[x] = true;// 只要被当前节点更新了就放入优先队列中for (int[] y: g[x]) {               // 这个循环最多被执行 m 次(因为有 m 条边)if (dis[y[0]] > d + y[1]) {dis[y[0]] = d + y[1];pq.offer(new int[]{y[0], dis[y[0]]});}}}System.out.println(dis[n] == 0x3f3f3f3f? -1: dis[n]);;}
}

bellman-ford

枚举 n 次:每次 循环所有边 a, b, wdis[b] = min(dis[b], dis[a] + w)

循环完之后, 所有节点会满足 dis[b] <= dis[a] + w。
在这里插入图片描述

对于 n 次循环中的第 k 次循环,求出的是 : 从 起点走 不超过 k 条边 的最短距离。
因此 如果第 n 次循环时有更新,说明图中存在负环。

例题:853. 有边数限制的最短路

https://www.acwing.com/problem/content/description/855/
在这里插入图片描述
注意! : 如果有负权回路,那么最短路就一定不存在了!

bellman-ford 算法可以判断出 图中是否存在负权回路。(但是一般使用 spfa 来判断是否有负环)

Q:这道题为什么必须使用 bellman-ford 算法?
A:因为限制了最多经过 k 条边,即存在边数限制。

import java.util.*;public class Main {public static void main(String[] args){Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(), m = scanner.nextInt(), k = scanner.nextInt();// 存储所有边int[][] edges = new int[m][3];for (int i = 0; i < m; ++i) {edges[i][0] = scanner.nextInt();edges[i][1] = scanner.nextInt();edges[i][2] = scanner.nextInt();}int[] dis = new int[n + 1], last;Arrays.fill(dis, 0x3f3f3f3f);dis[1] = 0;// 限制 k 次。  (k 次就表示最多经过 k 条边)for (int i = 0; i < k; ++i) {last = Arrays.copyOf(dis, n + 1);       // 将dis数组先备份一下for (int j = 0; j < m; ++j) {           // 枚举所有边dis[edges[j][1]] = Math.min(dis[edges[j][1]], last[edges[j][0]] + edges[j][2]);}}// 因为存在负权边,而本题的数据范围最多减 500 * 10000。所以和 0x3f3f3f3f/2 比较大小System.out.println(dis[n] > 0x3f3f3f3f / 2? "impossible": dis[n]);}
}

为什么需要对 dis 数组进行备份?

在这里插入图片描述
因为如果不备份的话可能会发生串联,为了避免串联,每次更新时只用上一次的结果。

比如上图,在第一次循环中 2 的 dis 被更新成了 1,如果不使用备份的话,那么 3 的 dis 会被接着更新为 2,但这并不是我们所期望的, 3 的 dis 被更新成 2 应该是在第 2 次循环时才会发生的事情。

spfa算法(bellman-ford 算法的优化)

相当于对 bellman-ford 算法做了一个优化。

bellman-ford 在每次循环中枚举了所有边,但实际上有些边并不会对松弛有作用,所以 spfa 就是从这一点进行了优化。
使用队列宽搜进行优化)。

在这里插入图片描述

从公式 d i s [ b ] = m i n ( d i s [ b ] , d i s [ a ] + w ) dis[b] = min(dis[b], dis[a] + w) dis[b]=min(dis[b],dis[a]+w) 可以看出,只有当 d i s [ a ] dis[a] dis[a] 变小了,这条边才有可能让 d i s [ b ] dis[b] dis[b] 跟着变小。


算法步骤:
在这里插入图片描述
基本思想:只有我变小了,我后面的人才会跟着变小

队列里面存的是待更新的点,就是等着用来更新其它点的点。

例题:851. spfa求最短路

https://www.acwing.com/activity/content/problem/content/920/
在这里插入图片描述

这一题的数据保证了图中不存在负环。


代码中不再是 n 次循环嵌套 m 次循环的 bellman-ford 算法了,
而是一个队列维护可以用来更新其它节点的节点队列,初始时放入起始节点 1,其余时间每次取出队首的节点即可。
取出一个节点后,枚举它影响的所有其它节点即可,如果其它节点被影响了,就表示可以把这个被影响的节点放入队列中,(不过放进队列之前要先判断一下是否已经在队列中了,防止重复更新)。

import java.util.*;public class Main {public static void main(String[] args){Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(), m = scanner.nextInt();// 使用邻接表存储List<int[]>[] g = new ArrayList[n + 1];Arrays.setAll(g, e -> new ArrayList<int[]>());for (int i = 0; i < m; ++i) {g[scanner.nextInt()].add(new int[]{scanner.nextInt(), scanner.nextInt()});}// 初始化距离、队列、是否在队列里的状态int[] dis = new int[n + 1];Arrays.fill(dis, 0x3f3f3f3f);dis[1] = 0;Queue<Integer> q = new LinkedList<Integer>();q.offer(1);boolean[] st = new boolean[n + 1];st[1] = true;while (!q.isEmpty()) {int t = q.poll();st[t] = false;for (int[] y: g[t]) {int j = y[0], w = y[1];if (dis[j] > dis[t] + w) {dis[j] = dis[t] + w;// 由于 j 变小了,所以它可以被更新,可以放入队列中// 但是放进去之前要先判断已经是否已经在队列中了,防止重复放置if (!st[j]) {q.offer(j);st[j] = true;}}}}System.out.println(dis[n] == 0x3f3f3f3f? "impossible": dis[n]);}
}

例题:852. spfa判断负环

https://www.acwing.com/problem/content/description/854/

在这里插入图片描述

跟 bellman-ford 算法判断负环的思路差不多,在更新 dis 数组的同时,维护一个 cnt 数组,cnt[x] 表示当前这个最短路的经过的边数。

每次更新 dis[x] 的时候,就把 cnt[x] 更新成 cnt[t] + 1。(因为 x 是从节点 t 更新过来的)。

如果在更新的过程中出现了 cnt[x] >= n,就表示至少经过了 n 条边,即至少经过了 n + 1 个点,这肯定是不合理的,说明存在负环。

import java.util.*;public class Main {public static void main(String[] args){Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(), m = scanner.nextInt();// 使用邻接表存储List<int[]>[] g = new ArrayList[n + 1];Arrays.setAll(g, e -> new ArrayList<int[]>());for (int i = 0; i < m; ++i) {g[scanner.nextInt()].add(new int[]{scanner.nextInt(), scanner.nextInt()});}System.out.println(spfa(g, n)? "Yes": "No");}static boolean spfa(List<int[]>[] g, int n) {// 初始化距离、队列、是否在队列里的状态int[] dis = new int[n + 1], cnt = new int[n + 1];Arrays.fill(dis, 0x3f3f3f3f);dis[1] = 0;boolean[] st = new boolean[n + 1];Queue<Integer> q = new LinkedList<Integer>();// 是判断是否存在负环,而不是只判断从1开始是否存在负环for (int i = 1; i <= n; ++i) {q.offer(i);st[i] = true;}while (!q.isEmpty()) {int t = q.poll();st[t] = false;for (int[] y: g[t]) {int j = y[0], w = y[1];if (dis[j] > dis[t] + w) {dis[j] = dis[t] + w;cnt[j] = cnt[t] + 1;if (cnt[j] >= n) return true;       // 表示有负环// 由于 j 变小了,所以它可以被更新,可以放入队列中// 但是放进去之前要先判断已经是否已经在队列中了,防止重复放置if (!st[j]) {q.offer(j);st[j] = true;}}}}return false;       // false表示没有负环}
}

Floyd(很暴力的三重循环)

https://oi-wiki.org/graph/shortest-path/#floyd-%E7%AE%97%E6%B3%95

用于求多源汇最短路。可以求任意两个结点之间的最短路。

使用邻接矩阵将原图存储下来,三重循环

d[i][j]for (int k = 1; k <= n; ++k) {for (int i = 1; i <= n; ++i) {for (int j = 1; j <= n; ++j) {// 看看i直接到j更近还是 经过k之后更近d[i][j] = min(d[i][j], d[i][k] + d[k][j]);	}}
}

原理其实是基于:动态规划

例题:854. Floyd求最短路

https://www.acwing.com/problem/content/856/

在这里插入图片描述

题目数据保证了不存在负权回路。

同样要注意最后各个距离要和 INF / 2 比较而不是和 INF 比较,因为图中可能存在负权。

import java.util.*;public class Main {public static void main(String[] args){Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(), m = scanner.nextInt(), t = scanner.nextInt(), INF = (int)1e9;// 建图int[][] g = new int[n + 1][n + 1];for (int i = 1; i <= n; ++i) {for (int j = 1; j <= n; ++j) {if (i == j) g[i][j] = 0;else g[i][j] = INF;}}for (int i = 0; i < m; ++i) {int x = scanner.nextInt(), y = scanner.nextInt(), z = scanner.nextInt();g[x][y] = Math.min(g[x][y], z);}// 求多源最短路for (int k = 1; k <= n; ++k) {for (int i = 1; i <= n; ++i) {for (int j = 1; j <= n; ++j) {g[i][j] = Math.min(g[i][j], g[i][k] + g[k][j]);}}}// 回答询问while (t-- != 0) {int x = scanner.nextInt(), y = scanner.nextInt();System.out.println(g[x][y] > INF / 2? "impossible": g[x][y]);   // 由于有负权,所以和INF/2比较}}
}

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

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

相关文章

npm i babel-plugin-import -D之后报错

替换modules/.bin/XX文件 1.vue-cli-service #!/bin/sh basedir$(dirname "$(echo "$0" | sed -e s,\\,/,g)")case uname in*CYGWIN*) basedircygpath -w "$basedir";; esacif [ -x "$basedir/node" ]; then"$basedir/node"…

【NLP】视觉变压器与卷积神经网络

一、说明 本篇是 变压器因其计算效率和可扩展性而成为NLP的首选模型。在计算机视觉中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;架构仍然占主导地位&#xff0c;但一些研究人员已经尝试将CNN与自我注意相结合。作者尝试将标准变压器直接应用于图像&#xff0c;发现在…

CAXA中.exb或者.dwg文件保存为PDF

通常CAXAZ中的文件为.exb或者.dwg格式&#xff0c;我们想打印或者保存为PDF文件格式&#xff0c;那么就用一下的方法&#xff1a; CAXA文件如图所示&#xff1a; 框选出你要打印的图纸&#xff01;&#xff01;&#xff01;&#xff01; 我们选择"菜单"->"…

【算法基础:搜索与图论】3.5 求最小生成树算法(PrimKruskal)

文章目录 最小生成树介绍朴素Prim算法算法思路⭐例题&#xff1a;858. Prim算法求最小生成树 Kruskal算法算法思路⭐例题&#xff1a;859. Kruskal算法求最小生成树 最小生成树介绍 最小生成树 有关树的定义 生成子图&#xff1a;生成子图是从原图中选取部分节点以及这些节点…

Keepalived热备、Keepalived+LVS、HAProxy监控及后端服务器健康检查、负载均衡调度器对比

day02 day02KeepAlived高可用集群配置高可用的web集群监控本机80端口&#xff0c;实现主备切换实现原理实施配置高可用、负载均衡的web集群配置高可用、负载均衡HAProxy配置haproxy负载均衡调度器比较LVS&#xff08;Linux Virtual Server&#xff09;NginxHAProxy KeepAlive…

Pytorch个人学习记录总结 08

目录 神经网络-搭建小实战和Sequential的使用 版本1——未用Sequential 版本2——用Sequential 神经网络-搭建小实战和Sequential的使用 torch.nn.Sequential的官方文档地址&#xff0c;模块将按照它们在构造函数中传递的顺序添加。代码实现的是下图&#xff1a; 版本1—…

16_LinuxLCD驱动

目录 Framebuffer设备 LCD驱动简析 LCD驱动程序编写 LCD屏幕参数节点信息修改 LCD 屏幕背光节点信息 使能Linux logo显示 设置LCD作为终端控制台 Framebuffer设备 先来回顾一下裸机的时候LCD驱动是怎么编写的,裸机LCD驱动编写流程如下: 1.初始化I.MX6U的eLCDIF控制器,…

Jenkins发送的邮箱中没有带配置的压缩附件

【问题描述】&#xff1a;Jenkins中明明配置了邮箱发送时要带压缩附件&#xff0c;收到的邮箱中却没有附件内容 【问题定位】&#xff1a;压缩附件没有放在Jenkins工作空间下&#xff0c;所以发送的邮件并未发送附件 【解决办法】&#xff1a; 1&#xff09;把压缩附件放到J…

kubernetes持久化存储卷

kubernetes持久化存储卷 kubernetes持久化存储卷一、存储卷介绍二、存储卷的分类三、存储卷的选择四、本地存储卷之emptyDir五、本地存储卷之 hostPath六、网络存储卷之nfs七、PV(持久存储卷)与PVC(持久存储卷声明)7.1 认识pv与pvc7.2 pv与pvc之间的关系7.3 实现nfs类型pv与pvc…

Spring MVC拦截器和跨域请求

一、拦截器简介 SpringMVC的拦截器&#xff08;Interceptor&#xff09;也是AOP思想的一种实现方式。它与Servlet的过滤器&#xff08;Filter&#xff09;功能类似&#xff0c;主要用于拦截用户的请求并做相应的处理&#xff0c;通常应用在权限验证、记录请求信息的日志、判断用…

EfficientNetV2: Smaller Models and Faster Training

EfficientNetV2: Smaller Models and Faster Training 1.Abstract 本文提出了一种训练速度快、参数量少、模型小的卷积神经网络EfficientNetV2。 训练采用了NAS感知技术与缩放技术对训练速度与参数数量进行联合优化。 NAS感知技术&#xff1a; 全名是神经架构搜索&#xff0…

quartus工具篇——ROM ip核

quartus工具篇——ROM ip核 1、ROM简介 FPGA中的ROM(Read-Only Memory)是一种只读存储器,主要用来存储固化的初始化配置数据。FPGA ROM的特性主要有: 预编程初始化 - ROM在FPGA编程时就已经写入了初始值,这些值在整个工作周期保持不变。初始化配置 - ROM通常用来存储FPGA的初…

Flutter的开发环境搭建-图解

前言&#xff1a;Flutter作为一个移动应用开发框架&#xff0c;具有许多优点和一些局限性。最大的优点就是-跨平台开发&#xff1a;Flutter可以在iOS和Android等多个平台上进行跨平台开发&#xff0c;使用一套代码编写应用程序&#xff0c;节省开发时间和成本。 Flutter可以编…

JVM运行时数据区——方法区、堆、栈的关系

方法区存储加载的字节码文件内的相关信息和运行时常量池&#xff0c;方法区可以看作是独立于Java堆的内存空间&#xff0c;方法区是在JVM启动时创建的&#xff0c;其内存的大小可以调整&#xff0c;是线程共享的&#xff0c;并且也会出现内存溢出的情况&#xff0c;也可存在垃圾…

2023JAVA 架构师面试 130 题含答案:JVM+spring+ 分布式 + 并发编程》...

此文包含 Java 面试的各个方面&#xff0c;史上最全&#xff0c;苦心整理最全 Java 面试题目整理包括基JVM算法数据库优化算法数据结构分布式并发编程缓存等&#xff0c;使用层面广&#xff0c;知识量大&#xff0c;涉及你的知识盲点。要想在面试者中出类拔萃就要比人付出更多的…

3.18 Bootstrap 列表组(List Group)

文章目录 Bootstrap 列表组&#xff08;List Group&#xff09;向列表组添加徽章向列表组添加链接向列表组添加自定义内容 Bootstrap 列表组&#xff08;List Group&#xff09; 本章我们将讲解列表组。列表组件用于以列表形式呈现复杂的和自定义的内容。创建一个基本的列表组的…

Debug Stable Diffusion webui

文章目录 SD前期预备一些惊喜TorchHijackForUnet Txt2Img 搭配 Lora 使用单独运行 txt2img.py获取所有资源代码地址参数sd model 主程序代码地址参数(同上)模型InferenceLORA应用重构并使用LORA模型用Lora重构后的网络 做 sampler后处理 以下内容是最近的学习笔记&#xff0c;如…

MySQL基础语法(DDL、DQL、DML、DCL)

目录 SQL通用语法以及分类 SQL通用语法 SQL语句的分类 数据库/表/列的命名规则 DDL语句 DDL设计的数据类型 数据库操作 表操作&#xff08;必须先进入到数据库&#xff09; DQL语句 DQL的执行顺序 基本查询 SELECT 条件查询 WHERE 分组查询 GROUP BY 排序查询 OR…

Python Flask构建微信小程序订餐系统 (十)

🔥 编辑会员信息 🔥 编辑会员信息可以通过点击会员列表操作,也可以点击会员信息详情点击进行操作 🔥 修改编程会员信息列表布局 🔥 修改 web/templates/member/index.html 文件,添加跳转到编辑会员信息的页面 web/templates/member/set.html 🔥 创建用于会员…

python机器学习(四)线性代数回顾、多元线性回归、多项式回归、标准方程法求解、线性回归案例

回顾线性代数 矩阵 矩阵可以理解为二维数组的另一种表现形式。A矩阵为三行两列的矩阵&#xff0c;B矩阵为两行三列的矩阵&#xff0c;可以通过下标来获取矩阵的元素&#xff0c;下标默认都是从0开始的。 A i j : A_{ij}: Aij​:表示第 i i i行&#xff0c;第 j j j列的元素。…