《啊哈算法》第四章之深度优先搜索

news2024/11/23 19:22:03

✌好听的歌一起分享! 

稻香 (女声版) - 余不不 - 单曲 - 网易云音乐

目录

模板

例子

1,关于遍历

2,关于边界

正文 

1,概念

2,解救小哈

例子源码和题目 

 1,小学奥数

 2,全排列

 3,组队

递归中的return

dfs中隐式return


模板

关于dfs,先来个模板,它分为遍历边界两部分

模板不是万能的,它只是一种思路

void dfs(int step)
{

    for(遍历每一种可能) {

            ......

            book[i] = 1;(标记)

            dfs(step + 1);(递归)

            book[i] = 0;(取消标记)

    }

    if(判断边界) {

            ......

            return;(返回上一步)

    }

}

一个if判断边界,判断后,还要return到最近调用的地方

一个for用来遍历,遍历后,还要标记,递归,取消标记 

例子

1,关于遍历

对比几个例子,从对比中加深对dfs模板的理解

for(int i = 0; i < 20; ++i)//一个for遍历20个队员
    if(book[i] == 0)//如果他没被访问
    {
        book[i] = 1;//标记
        dfs(index+1, sum+a[i][index]);//递归
        book[i] = 0;//取消标记
    }
for(int i = 1; i <= n; ++i)
    if(book[i] == 0) { //数字i没放入
        a[place] = i; //把i放入第place个盒子
        book[i] = 1; //标记
        dfs(place + 1); //递归下一个盒子
        book[i] = 0; //取消标记
    }
for(int i = 1; i <= 9; ++i) 
    if(book[i] == 0) {//数字i未被选中
        a[place] = i; //扑克i放入第place号盒子
        book[i] = 1; //标记
        dfs(place + 1); //递归
        book[i] = 0; //取消标记
    }

2,关于边界

if(index == 6)//一个if判断边界
    {
        max_score = max(max_score, sum);
        return; //返回上一步
        //return不能去掉
    }
if(place == n + 1) {//到达最后一个盒子的下一个
    ans++; //总共的可能
    for(int i = 1; i <= n; ++i)
        cout<<a[i];
    cout<<endl;
    return; //返回上一个盒子(最近一次调用dfs的地方)
    //return可去
    }
if(place == 10) { //来到不存在的第10个盒子,已结束
    if(a[1]*100+a[2]*10+a[3] + a[4]*100+a[5]*10+a[6] == a[7]*100+a[8]*10+a[9]) {
        ans++;
        printf("%d%d%d+%d%d%d=%d%d%d\n",a[1],a[2],a[3],
                a[4],a[5],a[6],a[7],a[8],a[9]);
    }
    return; //返回上一个盒子
    //这里return可去掉,输出不变
}

正文 

1,概念

理解递归的前提,是理解递归😀

这些简单的例子,核心代码不超过20行,却饱含深度优先搜索(Depth First Search, DFS)的基本模型

理解深度优先搜索的关键在于解决“当下该如何做”。

至于“下一步如何做”则与“当下该如何做”是一样的。

比如我们写的dfs(step)函数的主要功能就是解决当你在第step个盒子的时候你该怎么办

通常的方法就是把每一种可能都去尝试一遍(一般用for循环来遍历)。

当前这一步解决后便进入下一步dfs(dfs + 1)

下一步的解决方法和当前这步解决方法是完全一样的

再看个递归路线图

1、访问顶点a
2、依次从a的未被访问的邻接点出发,对图进行深度优先遍历;直至图中所有和a有路径相通的顶点被访问💪
3、若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止

路径:

a  b  d  h  d  b  e  i  e  j  e  b  a  c  f  k  f  c  g(橙色表示初次经过)

过程描述:

第一条路访问了a,b,d,h,走到底了,就从h退回(1)d,发现节点d没有除h以外的没访问过的,就退回(2)b,b有除d以外未访问过的e,所以又从e开始进行dfs...

被访问的顺序:

a --> b --> d --> h --> e --> i --> j --> c --> f --> k --> g

2,解救小哈

 题目

1,有一天,我的女朋友一个人去玩迷宫,因为方向感很差,迷路了,我得知后马上去解救她

2,迷宫由m行n列的单元格组成(m和n都小于100),每个单元格要么是空地,要么是障碍

3,我的任务是帮助女朋友找到一条从迷宫起点通向女朋友位置的最短路径

4,注意障碍是不能走的,也不能走到迷宫外

思路

开始套模板吧!

1,首先我们用一个二维数组a存储这个迷宫

2,假设一开始我在迷宫入口处(1,1),女朋友在(p, q),就要找(1,1)到(p,q)的最短路径

3,一开始只能往右或下走,到底往哪个方向走呢?只能一个一个方向尝试

4,于是我们建立一个方向数组,使用循环很容易得到下一步坐标

int next[4][2] = { //方向数组,循环得到下一步坐标
        {-1,0}, //上
        {1, 0}, //下
        {0,-1}, //左
        {0, 1}};//右

遍历所有点怎么遍历呢?

int tx, ty; //作为临时变量
    for(int i = 0; i < 4; ++i) {
        tx = x + next[i][0];
        ty = y + next[i][1];
}

接下来,还需要补充遍历的内容

1,判断是否超出迷宫范围

2,判断到达的地方是否是空地且没有走过 

int tx, ty; //作为临时变量
    for(int i = 0; i < 4; ++i) {
        tx = x + next[i][0];
        ty = y + next[i][1];
        //判断越界
        if(tx < 1 || ty < 1 || tx > m || ty > n)
            continue; //跳出本次循环
        //空地且未走过
        if(a[tx][ty] == 0 && book[tx][ty] == 0) {
            book[tx][ty] = 1; //标记
            dfs(tx, ty, step + 1); //递归
            book[tx][ty] = 0; //取消标记
        }
    }

接下来,需要判断边界,也就是是否到达了女朋友那里,我们用ans保留当前最短路径

//判断边界,本题为小哈位置
    if(x == p && y == q) {
        ans = min(ans, step);
        return; //返回上一步
    }

完整代码 

#include<iostream>
using namespace std;
int a[100][100], book[100][100], ans = 6666666;
int p, q; //小哈坐标
int m, n; //迷宫的行,列
void dfs(int x, int y, int step)
{
    int next[4][2] = { //方向数组,循环得到下一步坐标
        {-1,0}, //上
        {1, 0}, //下
        {0,-1}, //左
        {0, 1}};//右
    //枚举四种走法
    int tx, ty; //作为临时变量
    for(int i = 0; i < 4; ++i) {
        tx = x + next[i][0];
        ty = y + next[i][1];
        //判断越界
        if(tx < 1 || ty < 1 || tx > m || ty > n)
            continue; //跳出本次循环
        //空地且未走过
        if(a[tx][ty] == 0 && book[tx][ty] == 0) {
            book[tx][ty] = 1; //标记
            dfs(tx, ty, step + 1); //递归
            book[tx][ty] = 0; //取消标记
        }
    }
    //判断边界,本题为小哈位置
    if(x == p && y == q) {
        ans = min(ans, step);
        return; //返回上一步
    }
}
int main()
{
    int startx, starty; //初始位置坐标
    cin>>m>>n;
    for(int i = 1; i <= m; ++i)
        for(int j = 1; j <= n; ++j)
            cin>>a[i][j];
    cin>>startx>>starty>>p>>q;
    book[startx][starty] = 1; //标记初始已走过
    dfs(startx, starty, 0);
    cout<<ans;
    return 0;
}
5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 1 4 3
7

原方案通过二维数组book,记录在迷宫中走过的点,迷宫越大,book数组占的空间越大

下面是在原代码基础上的优化,优化方法如下:

将到达过的点,在二维数组a中位置的值改为-1,未到达的点依然为0,障碍依然为1,容易区分,且占用内存少

优化代码

#include<iostream>
using namespace std;
int a[100][100], ans = 6666666;
int p, q; //小哈坐标
int m, n; //迷宫的行,列
void dfs(int x, int y, int step)
{
    int next[4][2] = { //方向数组,循环得到下一步坐标
        {-1,0}, //上
        {1, 0}, //下
        {0,-1}, //左
        {0, 1}};//右
    //枚举四种走法
    int tx, ty; //作为临时变量
    for(int i = 0; i < 4; ++i) {
        tx = x + next[i][0];
        ty = y + next[i][1];
        //判断越界
        if(tx < 1 || ty < 1 || tx > m || ty > n)
            continue; //跳出本次循环
        //空地且未走过
        if(a[tx][ty] == 0) {
            a[tx][ty] = -1; //标记走过
            dfs(tx, ty, step + 1); //递归
            a[tx][ty] = 0; //取消标记
        }
    }
    //判断边界,本题为小哈位置
    if(x == p && y == q) {
        ans = min(ans, step);
        return; //返回上一步
    }
}
int main()
{
    int startx, starty; //初始位置坐标
    cin>>m>>n;
    for(int i = 1; i <= m; ++i)
        for(int j = 1; j <= n; ++j)
            cin>>a[i][j];
    cin>>startx>>starty>>p>>q;
    a[startx][starty] = -1; //标记初始已走过
    dfs(startx, starty, 0);
    cout<<ans;
    return 0;
}

仔细观察, 我们只修改了

第2行(去掉了全局变量book数组的声明

第23,25行(标记走过和未走过时,book改为a,赋值从1变成-1

第42行(初始标记走过从book[startx][starty] = 1改为a[startx][starty] = -1

-----------------------------------------------------------------------------------------------------------

例子源码和题目 

其中1,2可以去掉if判断边界中的return,3不能去掉,关于为什么,我猜是3中dfs递归时,存在两个变量

 1,小学奥数

Ubuntu Pastebin(源码)

□□□ + □□□ = □□□
将数字1 ~ 9分别填入 □ 种,每个数字只能使用一次使等式成立

比如173 + 286 = 459 与 286 + 173 = 459 为一种可能

#include<iostream>
#include<cstdio> //printf()
using namespace std;
int a[10], book[10], ans = 0; //全局变量
void dfs(int place)
{
    for(int i = 1; i <= 9; ++i) {
        if(book[i] == 0) {//数字i未被选中
            a[place] = i; //扑克i放入第place号盒子
            book[i] = 1; //标记
            dfs(place + 1); //递归
            book[i] = 0; //取消标记
        }
    }
    if(place == 10) { //来到不存在的第10个盒子,已结束
        if(a[1]*100+a[2]*10+a[3] + a[4]*100+a[5]*10+a[6]
           == a[7]*100+a[8]*10+a[9]) {
            ans++;
            printf("%d%d%d+%d%d%d=%d%d%d\n",a[1],a[2],a[3],
                   a[4],a[5],a[6],a[7],a[8],a[9]);
        }
        return; //返回上一个盒子
        //这里return可去掉,输出不变
    }
}

int main()
{
    dfs(1); //从第一个盒子开始
    cout<<ans / 2<<endl;
    return 0;
}
......(一共336行,所以是168种可能)
748+215=963
752+184=936
754+182=936
762+183=945
763+182=945
782+154=936
782+163=945
783+162=945
784+152=936
168

 2,全排列

Ubuntu Pastebin (源码)

小哼要将编号为1,2......n的n张扑克放到编号为1,2......n的n个盒子里,每个盒子有且只能放一张扑克,问一共有多少种不同放法(全排列)(n <= 9)

#include<iostream>
using namespace std;
int a[10], book[10], n, ans = 0;
void dfs(int place)
{
    for(int i = 1; i <= n; ++i) {
        if(book[i] == 0) { //数字i没放入
            a[place] = i; //把i放入第place个盒子
            book[i] = 1; //标记
            dfs(place + 1); //递归下一个盒子
            book[i] = 0; //取消标记
        }
    }
    if(place == n + 1) {//到达最后一个盒子的下一个
        ans++; //总共的可能
        for(int i = 1; i <= n; ++i)
            cout<<a[i];
        cout<<endl;
        return; //返回上一个盒子(最近一次调用dfs的地方)
        //return可去
    }
}
int main()
{
    cin>>n;
    dfs(1); //从第一个盒子开始
    cout<<ans<<endl;
    return 0;
}
3
123
132
213
231
312
321
6

4的话有24种,5的话有120种....

 3,组队

Ubuntu Pastebin(源码)

2019蓝桥杯C/C++B组ヽ(✿゚▽゚)ノ

作为篮球队教练,你需要从以下名单中选出 1 号位至 5 号位各一名球员,
组成球队的5人首发阵容。
每位球员担任 1 号位至 5 号位时的评分如下表所示。请你计算首发阵容 1
号位至 5 号位的评分之和最大可能是多少?

在这里插入图片描述

#include<iostream>
using namespace std;
int book[20], max_score = 0;
int a[20][6] = //声明初始化二维数组存储表格数据
{
    {1,97,90,0,0,0},
    {2,92,85,96,0,0},
    {3,0,0,0,0,93},
    {4,0,0,0,80,86},
    {5,89,83,97,0,0},
    {6,82,86,0,0,0},
    {7,0,0,0,87,90},
    {8,0,97,96,0,0},
    {9,0,0,89,0,0},
    {10,95,99,0,0,0},
    {11,0,0,96,97,0},
    {12,0,0,0,93,98},
    {13,94,91,0,0,0},
    {14,0,83,87,0,0},
    {15,0,0,98,97,98},
    {16,0,0,0,93,86},
    {17,98,83,99,98,81},
    {18,93,87,92,96,98},
    {19,0,0,0,89,92},
    {20,0,99,96,95,81}
};
//index表示当前位置, sum是当前组合总分
void dfs(int index, int sum)
{
    if(index == 6)//一个if判断编辑
    {
        max_score = max(max_score, sum);
        return; //返回上一步
        //return不能去掉
    }
    for(int i = 0; i < 20; i++)//一个for遍历20个队员
        if(book[i] == 0)//如果他没被访问
        {
            book[i] = 1;//标记
            dfs(index+1, sum+a[i][index]);//递归
            book[i] = 0;//取消标记
        }
}
int main()
{
    dfs(1, 0); //第一个成员开始,总分为0
    cout<<max_score<<endl;
    return 0;
}
490

 --------------------------------------------------------------------------------------

递归中的return

1,C++ 递归函数中的return是指:
从被调用函数返回到主调函数中继续执行,并非一遇到return整个递归结束

2,return 语句,顾名思义是终止当前正在执行的函数并将控制权返回到调用该函数的地方

3,在void的函数中也可以多次使用return,功能和循环中的break一样,在中间位置提前退出正在执行函数,也就是回到原来位置执行下一行代码

4,return; 表示结束本次函数

5,⭐递归中的return常用来作为递归终止的条件,当达到递归终止条件时,首先return的是最底层调用的函数,return之后,继续执行上一层调用该函数之后的代码⭐

在我对return进行理解时,这篇200收藏的文章给了我一定启发关于递归中return的理解(最浅显易懂)_Pledgee的博客-CSDN博客_递归函数return怎么理解

--------------------------------------------------------------------------------------

dfs中隐式return

隐式return的情况是,执行完函数后,自动返回上一级

 1,走方格

题目

给定一个m*n方格阵,沿着方格边线走,从左上角(0, 0)开始,每次只能往右或往下走一个单位距离,问走到右下角(m, n)一共有多少种不同走法

输入

一行包含两个整数 m 和 n (m >= 1 && m <= 10) && (n >= 1 && n <= 10)

输出

输出一个整数,表示走法数量

解析 

代码

#include<iostream>
using namespace std;
int m, n, num = 0;
int dfs(int x, int y)
{
    if(x == m && y == n)
        num++;//走法数量+1
    else
    {
        if(x < m)
            dfs(x + 1, y);//递归行加一
        if(y < n)
            dfs(x, y + 1);//递归列加一
    }
}
int main()
{
    while(cin>>m>>n)
    {
        dfs(0, 0);
        cout<<num<<endl;
        num = 0;
    }
    return 0;
}
3 2
10
5 5
252
10 10
184756

2,例子2

例子2只为说明隐式return(不需要return的情况)

#include <iostream>
using namespace std;

void dfs(int n)
{
    cout << "level: " << n << endl;/*1*/
    if (n < 4)
        dfs(n + 1);
    cout << "level: " << n << endl;/*2*/
}
int main()
{
    dfs(1);
    return 0;
}

输出:

lever: 1(执行/*1*/)
lever: 2(执行/*1*/)
lever: 3(执行/*1*/)
lever: 4(执行/*1*/)
lever: 4(执行完/*2*/后,函数返回上一级dfs递归的下一行
lever: 3(同上)
lever: 2(同上)
lever: 1(同上)

level: 1
level: 2
level: 3
level: 4
level: 4
level: 3
level: 2
level: 1

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

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

相关文章

【自学Docker 】Docker inspect命令

Docker inspect命令 大纲 docker inspect教程 使用 docker inspect 命令可以用来获取 Docker容器 或者 Docker镜像 的元数据。该命令后面的 CONTAINER 可以是容器Id&#xff0c;或者是容器名。 docker inspect语法 haicoder(www.haicoder.net)# docker inspect [OPTIONS] N…

python小知识

一、pip config list -v#pip在哪里寻找pip.conf文件 阿里云镜像&#xff1a; 二、安装anaconda(阿里云镜像库) 1、安装完成&#xff0c;命令行输入&#xff1a;conda config生成.condarc文件&#xff08;运行期配置文件&#xff09; 2、如果原本的源中的源地址是 https&…

webService速通教学(送源码)

什么是WebService webService是一种古老的互联网通讯方法。通过http通讯&#xff0c;将数据封装成XML的形式在网络中传输。习惯Java开发的伙伴肯定会对其嗤之以鼻&#xff0c;为什么不用Json传输&#xff0c;为什么不直接通过url拼参数&#xff1f;最大的两个因素是&#xff1…

Nginx基础03:配置文件nginx.conf(Part2)

上一篇文章概述与罗列了"全局配置块、events配置块、http全局块"的基本配置与属性&#xff0c;本篇文章将继续深入server块的配置项&#xff0c;以及相关应用。上篇文章地址&#xff1a;Nginx基础02&#xff1a;配置文件nginx.conf&#xff08;Part1&#xff09;如何…

从“工业报国为己任”到“科技创造优质生活”——华阳集团三十周年记

2022年10月28日&#xff0c;ADAYO华阳集团(002906.SZ)发布了一份“亮眼”的三季报。2022年1-9月公司实现营业收入40.08亿元&#xff0c;同比增长28.03%&#xff0c;实现归母净利润2.67亿元&#xff0c;同比增长28.28%。其中第三季度营业收入、净利润绝对值均为上市以来单季度最…

Android 深入系统完全讲解(23)

OpenGL 和 OpenGLES 简介 OpenGL(Open Graphics Library)意为开放图形库&#xff0c;是一个跨平台的图形 API&#xff0c;用于指定 3D 图 形处理硬件中的软硬件编程接口。OpenGL 一般用于图形工作站&#xff0c;PC 端使用。由于性能和可 移植性等各方面原因&#xff0c;在移动端…

分享72个PHP源码,总有一款适合您

PHP源码 分享72个PHP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 72个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/11BEwLdHiZF0DqB3Bhb3FaQ?pwdjoxq 提取码&#xff…

使用docker搭建版本控制系统-SVN

作者简介&#xff1a;一名Linux运维工程师&#xff0c;主要分享自己遇到的学习过程与遇到的问题。 座右铭&#xff1a;选择时尽心&#xff0c;行动时尽力&#xff0c;坚持时无怨&#xff0c;结束时无悔。 个人公众号&#xff1a;早九晚十二&#xff0c;欢迎大家留言交流…

day41|● 343. 整数拆分 ● 96.不同的二叉搜索树

题目链接:343. 整数拆分 1.代码 暴力做法&#xff1a;n前进行组合搜索得出二维数组result存放结果&#xff0c;然后对里面的元素进行乘积&#xff0c;谁最大就是结果 2.递归做法 class Solution { public:int integerBreak(int n) {vector<int>f(n 5, 0);f[2] 1;for …

LinkedList链表知识点概括

作者&#xff1a;爱塔居的博客_CSDN博客-JavaSE,数据结构领域博主 专栏&#xff1a;数据结构 作者简介&#xff1a;大三学生&#xff0c;希望2023年迎来更优秀的自己&#xff01;希望跟大家一同进步~ 文章目录 前言 一、链表的基本概念 二、面试题实战 前言 顺序表/ArrayList:…

数据湖之Hudi基础:核心原理

继续Hudi核心概念 参考官网描述与尚硅谷hudi公开资料 文章目录基本概念时间轴TimeLine1.Instants action 在表上执行的操作类型2.Instant time3.State两个时间概念文件布局&#xff08;FileLayout&#xff09;索引 Index表类型&#xff08;Table Types&#xff09;Copy On Writ…

echarts:实现3D地图版块叠加动效散点效果

需求描述 如下图所示&#xff0c;展示3D效果的地图版块&#xff0c;并叠加显示动效散点&#xff1a; 实现思路 首先是3D地图版块效果的实现&#xff0c;可以参考广州3D地图&#xff1b;而动效散点的实现&#xff0c;可以参考地图发散分布。 这里再提一个经过尝试并不行的思…

【mmdeploy】mmseg转ONNX/TensorRT,附推理代码

目录 1.关于mmdeploy 2.环境安装 2.1预编译安装&#xff08;Linux-x86_64, CUDA 11.x, TensorRT 8.2.3.0&#xff09;&#xff1a; 2.2预编译安装&#xff08;Linux-x86_64, CUDA 11.x, ONNX&#xff09;&#xff1a; 3.mmseg工程torch转onnx 4.使用onnx模型文件进行推理…

Dubbo框架学习(第一章Dubbo简介)

由于在微服务领域有两大框架统治&#xff0c;一个是springCloud的全家桶&#xff0c;一个是Dubbo。我用Dubbo比较少&#xff0c;所以也是学习状态。Dubbo框架学习&#xff0c;资料来源于cn.dubbo.apache.org。第一章Dubbo简介Apache Dubbo 是一款 RPC 微服务框架&#xff0c;提…

字节跳动青训营--前端day2

文章目录前言一、css1. css的组成2. css三种使用方式3.css的工作方式二、 css选择器Selector1. 选择元素的方式2. 伪类&#xff08;pseudo-classes&#xff09;2.1 状态伪类2.1 结构伪类3.通过组合选择元素3.1 直接组合3.2 元素组合的拓展4. 选择器的特异度&#xff08;Specifi…

小型水库雨水情测报和安全监测解决方案

平升电子小型水库雨水情测报和安全监测解决方案辅助水利管理部门实现水库雨水情信息“全要素、全量程、全覆盖”自动测报。系统具备水库水位、雨量、现场图像/视频等水文信息采集、传输、处理及预警广播等功能&#xff0c;有效提升了雨水情信息的时效性和准确度&#xff0c;为保…

jmeter 使用beanshell 编写脚本

一、介绍 1.1 介绍 BeanShell是一个小型的、免费的、可嵌入使用Java编写的具有对象脚本语言特性的Java源码解释器。 动态执行所有Java语句、Java代码片段以及弱类型Java和附加的脚本的便利 透明地访问所有Java对象和API 四种运行模式&#xff1a;命令行、控制台、Applet、远…

数据结构专题 -- 哈希思想详解

代码会存放在&#xff1a; https://github.com/sjmshsh/Data-Struct-HandWriting 通过阅读本篇文章&#xff0c;你可以学到&#xff1a; 哈希思想及其本质使用C实现简易的哈希表哈希思想的应用 位图布隆过滤器哈希切分极致升华&#xff0c;海量数据处理面试题 拓展 – 一致性…

二叉树的应用——哈夫曼树

哈夫曼树与哈夫曼编码 1.树的带权路径长 百分制成绩转五级制的算法流程图&#xff08;A/B/C/D/E的人数分别为6/18/21/36/19&#xff09;带权路径长 路经长 x 权重 树的带权路经长&#xff1a;所有叶结点的带权路径长度之和。 例如&#xff1a; &#xff08;a&#xff09;图…

[ 攻防演练演示篇 ] 利用谷歌 0day 漏洞上线靶机

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…