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

【算法设计-搜索】回溯法应用举例(1)

文章目录

    • 0. 回溯模板
    • 1. 走楼梯
    • 2. 机器走格子,但限定方向
    • 3. 中国象棋,马走日字
    • 4. 走迷宫
    • 5. 积木覆盖

0. 回溯模板

搜索算法中的回溯策略,也是深度优先搜索的一种策略,比较接近早期的人工智能。毕竟,搜索是人工智能技术中进行问题求解的基本技术,很多问题都可以归结到某种搜索。

下面给出回溯算法的模板,很多题目其实可以套用该模板快速解决。但是请注意,深度优先搜索一般不能应用于求解最优解的问题上。

// node: 当前在回溯树中的结点
void trace (int node){if (当前结点 == 目标结点)输出方案;else{尝试所有满足条件的结点if (新结点符合条件){记录新结点;设置占位标志;trace(i+1);  // 进行下一结点的试探删除新结点;恢复占位标志;}}
}

接下来的例子将带领大家由浅入深、循序渐进走入回溯法的世界。

1. 走楼梯

【描述】楼梯有 n 级台阶(n ≤ 20),可以一步走 1 级,也可以一步走 2 级。输入一个正整数 n,请输出所有上楼梯的方案。

【输入和输出样例】

5
方案:1 1 1 1 1
方案:1 1 1 2
方案:1 1 2 1
方案:1 2 1 1
方案:1 2 2
方案:2 1 1 1
方案:2 1 2
方案:2 2 1

【简要算法描述】

  • 设置一个数组 record 记录每一次的走法(走一级台阶还是两级台阶?)
  • 设置一个变量 passed 记录走过的台阶数
// 第node步的试探:我该走一级台阶还是两级台阶?
void trace (int node){if (passed == 目标台阶数)输出方案;else{尝试走step级台阶(step=1,2if (可以走step级台阶){record[node] = step; // 记录passed = passed + step; // 占位trace(node+1);  // 试探下一步record[node] = 0; // 清除记录passed = passed - step; // 复位}}
}

【题解】

#include <cstdio>
#include <cstring>
using namespace std;// goal:目标台阶数, node:当前在回溯树中的结点/第node步, passed:记录走过的台阶数, record:记录走法方案 
void trace (int goal, int node, int passed, int record[]){if (passed == goal){  // 若正好走到目标台阶 node--;  // 则需修正当前结点printf("方案:");for (int i = 1; i <= node; i++)printf("%d ", record[i]);printf("\n");}else{for (int step = 1; step <= 2; step++){  // 尝试走一个台阶或两个台阶 if (passed + step <= goal){		    // 如果没有超出目标台阶数 record[node] = step;            // 则记录该走法passed += step;					// 并记录走过的台阶数(相当于占位) trace(goal, node+1, passed, record);  // 继续探索下一种走法,试探下一步该怎么走 record[node] = 0;               // 回溯,删除该走法(非必要操作) passed -= step;					// 回溯,回到没有走这一步之前的台阶上,为尝试下一种走法做准备(相当于恢复占位标志)}	}}
}int main(){int n;int A[100];while (scanf("%d", &n) != EOF){memset(A, 0, sizeof(A));trace(n, 1, 0, A);  // 当前处在回溯树的初始结点,走过的台阶数为0 }return 0;
}

通过该题想必可以了解到回溯算法的套路了,比较关键的无非就是五个步骤。下面的几题跟寻找路径有关,难度比第一题稍小。

2. 机器走格子,但限定方向

【描述】现有一个 4x4 的格子,给定一个起始坐标(m,n),只允许机器人向上或向右到达目标坐标点(4,4),请输出所有的机器人走法方案。

注:4x4 格子的横坐标范围为 1 ~ 4,纵坐标范围为 1 ~ 4,因此 m,n 值只能为 1 ~ 4。

【输入和输出样例 1】

2 3
方案:
0 0 0 0
0 0 1 0
0 0 1 0
0 0 1 1
方案:
0 0 0 0
0 0 1 0
0 0 1 1
0 0 0 1
方案:
0 0 0 0
0 0 1 1
0 0 0 1
0 0 0 1

【输入和输出样例 2】

3 2
方案:
0 0 0 0
0 0 0 0
0 1 0 0
0 1 1 1
方案:
0 0 0 0
0 0 0 0
0 1 1 0
0 0 1 1
方案:
0 0 0 0
0 0 0 0
0 1 1 1
0 0 0 1

【简要算法描述】

  • 设置一个数组 record 记录每一次的走法
// 当前机器人在坐标point处
void trace (point){if (point == 目标坐标)输出方案;else{尝试向上或向右if (可以向上或向右){record[point+向上或向右] = 1;trace(point+向上或向右);  // 试探下一步record[point+向上或向右] = 0;}}
}

【题解】

#include <cstdio>
#include <cstring>
using namespace std;struct Pos{  // 横坐标x和纵坐标y封装为一个 坐标点 结构体 int x;int y;Pos(int _x, int _y): x(_x), y(_y) {}// 重载运算符== bool operator == (const struct Pos &p){return p.x == x && p.y == y; }// 重载运算符<=bool operator <= (const struct Pos &p){return x <= p.x && y <= p.y; } // 重载运算符+,用于坐标点之间的运算 struct Pos operator + (const struct Pos &p){return Pos(x+p.x, y+p.y);}
};#define MAX 4
int A[MAX+1][MAX+1] = {0};  // 记录走法方案,也兼具占位功能,1表示走过,0表示没走过 
struct Pos delta[2] = {Pos(1, 0), Pos(0, 1)};  // 只能向右走或向上走,用于改变 // goal:目标坐标, point:当前坐标, record:记录走法方案 
void trace (struct Pos goal, struct Pos point, int record[][MAX+1]){if (point == goal){  					// 若正好走到目标点,则输出方案 printf("方案:\n");for (int i = 1; i <= MAX; i++){for (int j = 1; j <= MAX; j++)printf("%d ", record[i][j]);printf("\n");}}else{for (int i = 0; i <= 1; i++){  							// 尝试向上或向右走 if (point + delta[i] <= Pos(MAX, MAX)){  			// 如果没有走出范围以外 struct Pos pointDelta = point + delta[i];record[pointDelta.x][pointDelta.y] = 1;         // 则记录该走法(或标记占位标志) trace(goal, pointDelta, record);     			// 继续探索下一种走法,遍历过的结点数加1 record[pointDelta.x][pointDelta.y] = 0;       	// 回溯,为尝试下一种走法做准备(或恢复占位标志) }	}}
}int main(){int m, n;while (scanf("%d%d", &m, &n) != EOF){struct Pos init(m, n);struct Pos goal(MAX, MAX);memset(A, 0, sizeof(A));A[init.x][init.y] = 1; // 起始点标记为走过 trace(goal, init, A);  // 当前处在回溯树的初始结点,走过的台阶数为0 printf("\n");}return 0;
}

3. 中国象棋,马走日字

【描述】中国棋盘大小为 8x9,假设马的初始位置在(0,0)处,现给定象棋棋盘中的一个点(m,n),请输出跳到(m,n)的总步数小于十步之内的方案,需要标出第几步走到了棋盘的哪个位置。

注意,由于遍历所有方案所用的时间已超出了可接受范围,因此请每输出一个方案使用system(“pause”)暂停程序运行。

【输入和输出示例】

3 3
方案:1  0  0  0  3  0  7  0  50  0  2  0  8  0  4  0  00  0  0  0  0  0  0  6  00  0  0  9  0  0  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  0
请按任意键继续. . .
方案:1  0  0  0  3  0  7  0  50  0  2  0  0  0  4  0  00  0  0  0  0  8  0  6  00  0  0  9  0  0  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  0
请按任意键继续. . .
方案:1  0  0  0  3  0  0  0  50  0  2  0  8  0  4  0  00  0  0  0  0  0  0  6  00  0  0  9  0  7  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  00  0  0  0  0  0  0  0  0
请按任意键继续. . .

【简要算法描述】

  • 设置一个数组 record 记录每一次的走法
// 当前马走到坐标point处,为第step步
void trace (point, step){if (point == 目标坐标)输出方案;else{从point开始,尝试下一步日字,得到新坐标if (新坐标可以走){record[新坐标] = step;trace(新坐标, step+1);  // 试探下一步record[新坐标] = 0;}}
}

【题解】

#include <cstdio>
#include <cstring>
#include <stdlib.h>
using namespace std;struct Pos{  // 横坐标x和纵坐标y封装为一个 坐标点 结构体 int x;int y;Pos(int _x, int _y): x(_x), y(_y) {}// 重载运算符== bool operator == (const struct Pos &p){return p.x == x && p.y == y; }// 重载运算符<=bool operator <= (const struct Pos &p){return x <= p.x && y <= p.y; } // 重载运算符+,用于坐标点之间的运算 struct Pos operator + (const struct Pos &p){return Pos(x+p.x, y+p.y);}
};#define MAX_X 8
#define MAX_Y 9
int A[MAX_X][MAX_Y];  // 记录走法方案,也兼具占位功能,非0表示走过,0表示没走过 
struct Pos delta[8] = { Pos(-2, 1), Pos(-1, 2), Pos(1, 2), Pos(2, 1),Pos(-2, -1), Pos(-1, -2), Pos(1, -2), Pos(2, -1)};  // goal:目标坐标, point:当前坐标, record:记录走法方案, step:记录走了多少步 
void trace (struct Pos goal, struct Pos point, int record[][MAX_Y], int step){if (step > 11)return;if (point == goal && step <= 11){  					// 若正好走到目标点,则输出方案 printf("方案:\n");for (int i = 0; i < MAX_X; i++){for (int j = 0; j < MAX_Y; j++)printf("%3d", record[i][j]);printf("\n");}system("pause");  // 不可能遍历所有方案,因此每输出一个方案暂停一下}else{for (int i = 0; i < 8; i++){  	struct Pos pointDelta = point + delta[i];			// 尝试不同的走法 if (Pos(0, 0) <= pointDelta && pointDelta <= Pos(MAX_X-1, MAX_Y-1) && record[pointDelta.x][pointDelta.y] == 0){ 	// 如果没有走出范围以外,以及该点未走过 record[pointDelta.x][pointDelta.y] = step;      // 则记录该走法(或标记占位标志) trace(goal, pointDelta, record, step+1);     	// 继续探索下一种走法,遍历过的结点数加1 record[pointDelta.x][pointDelta.y] = 0;       	// 回溯,为尝试下一种走法做准备(或恢复占位标志) }	}}
}int main(){int m, n;while (scanf("%d%d", &m, &n) != EOF){struct Pos init(0, 0);struct Pos goal(m, n);memset(A, 0, sizeof(A));A[0][0] = 1; // 起始点标记为第一步 trace(goal, init, A, 2);  // 从第二步开始走printf("\n");}return 0;
}

4. 走迷宫

【描述】给一张 6x6 迷宫地图,用“.”表示可以走的路,用“#”表示障碍物,以左上角(0,0)为起点,左下角(5,5)为终点,输出所有路径方案,用“Y”标记已经走过的路径。

【输入示例】

.#..#.
.##.#.
..#...
#...#.
.#.#..
#.....

【输出示例】

方案:
Y # . . # .
Y # # . # .
Y Y # . . .
# Y Y . # .
. # Y # . .
# . Y Y Y Y方案:
Y # . . # .
Y # # . # .
Y Y # . . .
# Y Y . # .
. # Y # Y Y
# . Y Y Y Y方案:
Y # . . # .
Y # # . # .
Y Y # Y Y Y
# Y Y Y # Y
. # . # . Y
# . . . . Y方案:
Y # . . # .
Y # # . # .
Y Y # Y Y Y
# Y Y Y # Y
. # . # Y Y
# . . . Y Y

【简要算法描述】

  • 将迷宫地图当做可以标记占位的数组
  • 注意,如果将迷宫地图定义为由 6 个字符串组成,则每个字符串最后的“\0”也要占位,所以申请数组时请申请 6x7 的大小
// 当前走到坐标point处
void trace (point){if (point == 目标坐标)输出方案;else{从point开始尝试下一步,得到新坐标if (新坐标没有超出范围,且不是障碍){record[新坐标] = 'Y';trace(新坐标, step+1);  // 试探下一步record[新坐标] = 0;}}
}

【题解】

#include <cstdio>
#include <cstring>
using namespace std;struct Pos{  // 横坐标x和纵坐标y封装为一个 坐标点 结构体 int x;int y;Pos(int _x, int _y): x(_x), y(_y) {}// 重载运算符== bool operator == (const struct Pos &p){return p.x == x && p.y == y; }// 重载运算符<=bool operator <= (const struct Pos &p){return x <= p.x && y <= p.y; } // 重载运算符+,用于坐标点之间的运算 struct Pos operator + (const struct Pos &p){return Pos(x+p.x, y+p.y);}
};#define MAX_X 6
#define MAX_Y 6
char A[MAX_X][MAX_Y+1] = {".#..#.",".##.#.","..#...","#...#.",".#.#..","#....."};  struct Pos delta[4] = {Pos(1, 0), Pos(0, 1), Pos(-1, 0), Pos(0, -1)};  // goal:目标坐标, point:当前坐标, record:记录走法方案
void trace (struct Pos goal, struct Pos point, char record[][MAX_Y+1]){if (point == goal){  					// 若正好走到目标点,则输出方案 printf("方案:\n");for (int i = 0; i < MAX_X; i++){for (int j = 0; j < MAX_Y; j++)printf("%c ", record[i][j]);printf("\n");}printf("\n");}else{for (int i = 0; i < 4; i++){  	struct Pos pointDelta = point + delta[i];			// 尝试不同的走法 if (Pos(0, 0) <= pointDelta && pointDelta <= Pos(MAX_X-1, MAX_Y) && record[pointDelta.x][pointDelta.y] == '.'){ 		// 如果没有走出范围以外,以及该点未走过或不是障碍 record[pointDelta.x][pointDelta.y] = 'Y';      		// 则记录该走法(或标记占位标志) trace(goal, pointDelta, record);     				// 继续探索下一种走法record[pointDelta.x][pointDelta.y] = '.';       	// 回溯,为尝试下一种走法做准备(或恢复占位标志) }	}}
}int main(){int m, n;struct Pos init(0, 0);struct Pos goal(5, 5);A[0][0] = 'Y'; // 起始点标记为走过 trace(goal, init, A);  printf("\n");return 0;
}

5. 积木覆盖

【描述】给定一个 6x6 的网格,用“#”表示被某块积木占用,用“.”表示没有被积木占用,请求出网格中一共有多少块积木,并输出每块积木的坐标。

【输入样例 1】

.#..#.
.#.##.
.#....
#...#.
.#.###
#....#

【输出样例 1】

第1块积木坐标:(1,1) (2,1) (0,1)
第2块积木坐标:(1,4) (0,4) (1,3)
第3块积木坐标:(3,0)
第4块积木坐标:(4,4) (4,5) (5,5) (3,4) (4,3)
第5块积木坐标:(4,1)
第6块积木坐标:(5,0)
共有6块积木

【输入样例 2】

.#..#.
.####.
.#....
#...#.
.#.###
#....#

【输出样例 2】

第1块积木坐标:(1,1) (2,1) (1,2) (1,3) (1,4) (0,4) (0,1)
第2块积木坐标:(3,0)
第3块积木坐标:(4,4) (4,5) (5,5) (3,4) (4,3)
第4块积木坐标:(4,1)
第5块积木坐标:(5,0)
共有5块积木

【分析】该题比“走迷宫”较简单,但相较于“走迷宫”,本题没有明显的递归回溯终止目标,因为这个目标是隐含的:当一块积木的所有格子都走完后,就代表回溯完毕。本题可以模仿“走迷宫”,先找出被积木占用的格子,即先找到“#”的坐标(相当于迷宫的入口,或某块积木的“入口”),然后开始寻找其他与之相邻的“#”,把“.”视为障碍物,把找到的“#”改为“Y”。

然而这里有个问题。如果回溯时把已走过的“Y”改回“#”,则下一次找到另一个“#”的坐标(相当于某块积木的“入口”),你如何保证是不是之前我们遍历过的同一块积木?所以我们不能把已走过的“Y”改回“#”,而是要改成别的符号,比如“V”,这样才能区分出哪块积木已经遍历过了,下一次就不用遍历了。

【简要算法描述】

// 当前走到坐标point处
void trace (point, map){从point开始尝试下一步,得到新坐标if (新坐标没有超出范围,且新坐标==“#”或“V”){map[新坐标] = 'Y';输出坐标;trace(新坐标, step+1);  // 试探下一步map[新坐标] = 'V';}}
}

【题解】

#include <cstdio>
#include <cstring>
using namespace std;struct Pos{  // 横坐标x和纵坐标y封装为一个 坐标点 结构体 int x;int y;Pos(int _x = 0, int _y = 0): x(_x), y(_y) {}// 重载运算符== bool operator == (const struct Pos &p){return p.x == x && p.y == y; }// 重载运算符<=bool operator <= (const struct Pos &p){return x <= p.x && y <= p.y; } // 重载运算符+,用于坐标点之间的运算 struct Pos operator + (const struct Pos &p){return Pos(x+p.x, y+p.y);}
};#define MAX_X 6
#define MAX_Y 6
// 积木地图 
char A[MAX_X][MAX_Y+1] = {".#..#.",".#.##.",".#....","#...#.",".#.###","#....#"};  // 记录一块积木的每个坐标
struct Pos record[MAX_X * MAX_Y]; // 方向变化数组 
struct Pos delta[4] = {Pos(1, 0), Pos(0, 1), Pos(-1, 0), Pos(0, -1)}; // point:当前坐标, map:标记了占位的地图, isOther:标记该积木除了占有该格子外没有别的格子 
void trace (struct Pos point, char map[][MAX_Y+1], bool &isOther){for (int i = 0; i < 4; i++){  	struct Pos pointDelta = point + delta[i];			// 尝试不同的走法if (Pos(0, 0) <= pointDelta && pointDelta <= Pos(MAX_X-1, MAX_Y)&& map[pointDelta.x][pointDelta.y] == '#' || map[pointDelta.x][pointDelta.y] == 'V'){ // 如果没有走出范围以外,以及该点未走过 map[pointDelta.x][pointDelta.y] = 'Y';      	// 则标记占位标志 isOther = true;									// 这块积木原来还占有别的格子 printf("(%d,%d) ", pointDelta.x, pointDelta.y); // 输出该格子的坐标 trace(pointDelta, map, isOther);     			// 继续探索下一块积木map[pointDelta.x][pointDelta.y] = 'V';       	// 回溯,恢复占位标志}	}
}int main(){int cnt = 0;bool isOther;for (int i = 0; i < MAX_X; i++){for (int j = 0; j < MAX_Y; j++){if (A[i][j] == '#'){  // 找到积木的入口 cnt++;isOther = false;printf("第%d块积木坐标:", cnt);trace(Pos(i, j), A, isOther);  // 开始寻找该积木的其他格子 if (!isOther)  // 如果该积木只占有一个格子,则只输出该格子的坐标 printf("(%d,%d)", i, j);printf("\n");}	}}	printf("共有%d块积木\n", cnt);return 0;
}

从下一篇开始,是有关数学智力题的回溯算法应用。

相关文章:

【算法设计-搜索】回溯法应用举例(1)

文章目录0. 回溯模板1. 走楼梯2. 机器走格子&#xff0c;但限定方向3. 中国象棋&#xff0c;马走日字4. 走迷宫5. 积木覆盖0. 回溯模板 搜索算法中的回溯策略&#xff0c;也是深度优先搜索的一种策略&#xff0c;比较接近早期的人工智能。毕竟&#xff0c;搜索是人工智能技术中…...

C++基础了解-23-C++ 多态

C 多态 一、C 多态 多态按字面的意思就是多种形态。当类之间存在层次结构&#xff0c;并且类之间是通过继承关联时&#xff0c;就会用到多态。 C 多态意味着调用成员函数时&#xff0c;会根据调用函数的对象的类型来执行不同的函数。 下面的实例中&#xff0c;基类 Shape 被…...

【GNN/深度学习】常用的图数据集(资源包)

【GNN/深度学习】常用的图数据集&#xff08;图结构&#xff09; 文章目录【GNN/深度学习】常用的图数据集&#xff08;图结构&#xff09;1. 介绍2. 图数据集2.1 Cora2.2 Citeseer2.3 Pubmed2.4 DBLP2.5 ACM2.6 AMAP & AMAC2.7 WIKI2.8 COCS2.9 BAT2.10 EAT2.11 UAT2.12 C…...

Clickhouse中bitmap介绍以及计算留存Demo

前言 参考了腾迅的大数据分析-计算留存,能够根据用户自定义属性,以及玩家行为进行留存的计算。最初计算留存的方法使用的是clickhosue自带的rentention函数,使用这个函数不用关注太多细节,只需要把留存条件放入函数即可。但是这个如果需要关联用户属性,就比较麻烦了。因此…...

大数据是什么?学习后能找高薪工作么

大数据是什么&#xff0c;比较官方的定义是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。 简单来说&#xff0c;大数据就是结构化的…...

如何提取视频中的音频转文字?分享提效减负视频转文字方法

最近我在学做短视频&#xff0c;就看了很多博主怎么做视频&#xff0c;像他们的拍摄方法、剪辑角度还有怎么写文案。我一开始只看了一两个博主&#xff0c;写文案时就是边看视频边打字&#xff0c;这视频量少还好&#xff0c;视频多了就觉得这种方法好费时间&#xff0c;感觉一…...

脑机接口科普0018——前额叶切除手术

本文禁止转载&#xff01;&#xff01;&#xff01; 首先说明一下&#xff0c;前额叶切除手术&#xff0c;现在已经不允许做了。 其次&#xff0c;前额叶切除手术&#xff0c;发明这个手术的人居然还获得了诺贝尔奖。太过于讽刺。1949年的那次诺贝尔医学奖&#xff08;就是我…...

FPGA工程师面试——基础知识

1. 简述FPGA等可编程逻辑器件设计流程 答&#xff1a;系统设计电路构思&#xff0c;设计说明与设计划分&#xff0c; 电路设计与输入&#xff08;HDL代码、原理图&#xff09;&#xff0c; 功能仿真与测试&#xff0c; 逻辑综合&#xff0c; 门级综合&#xff0c; 逻辑验证与测…...

全国青少年软件编程(Scratch)等级考试一级真题——2019.12

青少年软件编程&#xff08;Scratch&#xff09;等级考试试卷&#xff08;一级&#xff09;分数&#xff1a;100 题数&#xff1a;37一、单选题(共25题&#xff0c;每题2分&#xff0c;共50分)1.下列关于舞台的描述&#xff0c;不正确的是&#xff1f;&#xff08; &#xff09…...

【Integrated Electronics系列——数字电子技术基础】

目录 序言...

【微信小程序】-- 页面处理总结(三十一)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…...

Spring Batch使用详细例子

Spring Batch 是一个开源的批处理框架&#xff0c;它提供了一种简单的方式来处理大规模的数据处理任务。它基于 Spring 框架&#xff0c;可以与 Spring 的其他组件无缝集成&#xff0c;如 Spring Boot、Spring Data 等。本文将介绍如何使用 Spring Batch 进行批处理任务。 1. 准…...

漏洞预警|Apache Dubbo 存在反序列化漏洞

棱镜七彩安全预警 近日网上有关于开源项目Apache Dubbo 存在反序列化漏洞&#xff0c;棱镜七彩威胁情报团队第一时间探测到&#xff0c;经分析研判&#xff0c;向全社会发起开源漏洞预警公告&#xff0c;提醒相关安全团队及时响应。 项目介绍 Apache Dubbo 是一款 RPC 服务开…...

Tomcat源码分析-spring boot集成tomcat

SPI 在分析源码前&#xff0c;我们先来了解下 spring 的 SPI 机制。我们知道&#xff0c;jdk 为了方便应用程序进行扩展&#xff0c;提供了默认的 SPI 实现&#xff08;ServiceLoader&#xff09;&#xff0c;dubbo 也有自己的 SPI。spring 也是如此&#xff0c;他为我们提供了…...

一个古老的html后台的模板代码

效果图下&#xff1a; css部分代码&#xff1a;/* CSS Document / body{font-family:“宋体”, Arial,Verdana, sans-serif, Helvetica;font-size:12px;margin:0;background:#f4f5eb;color:#000;} dl,ul,li{list-style:none;} a img{border:0;} a{color:#000;} a:link,a:visit…...

支持向量回归删除异常值Python

1、支持向量回归&#xff08;SVR&#xff09;原理 支持向量回归&#xff08;Support Vector Regression&#xff0c;SVR&#xff09;不仅可以用于预测&#xff0c;还可以用于异常值检测。其基本思路是训练一个回归模型&#xff0c;通过对每个数据点进行预测&#xff0c;并计算…...

手把手开发一门程序语言JimLang (2)

根据爱因斯坦的相对论&#xff0c;物体的质量越大&#xff0c;时间过得越快&#xff0c;所以托更对于我的煎熬&#xff0c;远远比你们想象的还要痛苦…今天给大家来盘硬菜&#xff0c;也是前些时日预告过的JimLang的开发过程… Let’s go !!! 语法及解析 JimLang.g4 这里我们…...

DSF深度搜索时到底是如何回溯的(小tip)

这一段让我迷了两次&#xff0c;为什么回溯的时候&#xff0c;恢复了最后一位&#xff0c;往上递归一层之后&#xff0c;把最后一位填在它前一位&#xff0c;但是原本的前一位没有恢复&#xff0c;最后一位要怎么办&#xff1f;其实这还是递归没明白 也就是这一步是如何实现的 …...

Rust Web入门(八):打包发布

本教程笔记来自 杨旭老师的 rust web 全栈教程&#xff0c;链接如下&#xff1a; https://www.bilibili.com/video/BV1RP4y1G7KF?p1&vd_source8595fbbf160cc11a0cc07cadacf22951 学习 Rust Web 需要学习 rust 的前置知识可以学习杨旭老师的另一门教程 https://www.bili…...

synchronize优化偏向锁

偏向锁 轻量级锁在没有竞争时&#xff08;只有自己一个线程&#xff09;&#xff0c;仍然会尝试CAS替换mark word&#xff1b; 会造成一定的性能的损耗&#xff1b; JDK6之中引入了偏向锁进行优化&#xff0c;第一次使用时线程ID注入到Mark word中&#xff0c;之后重入不再进…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...