DFS与BFS

DFS与BFS

dfs又称深度优先搜索,即一路走到底(一个执着的人),当走到底(到达叶子节点)时要回溯。注:回溯不是直接回到头,而是边回去边看,能不能再往下走,只有当我们明确当前节点所有的路都走不通时才回退一步!

BFS又称广度优先搜索,即一层一层的搜索,只有当每一层搜索完之后才搜索下一层(一个稳重的人)

对比:

​ 数据结构 空间 特点
DFS : stack O(h)与高度成正比 不具有最短性
BFS: queue O(2的h次方) 具有最短性
都可以画搜索树进行理解!

DFS:

DFS即暴力搜索: 最重要的是把顺序弄清楚——要以一个怎样的顺序把所有方案遍历一遍,类似于树的先序遍历

回溯键值

数字排列

如何用 dfs 解决全排列问题?

dfs 最重要的是搜索顺序。用什么顺序遍历所有方案。

对于全排列问题,以 n = 3 为例,可以这样进行搜索:

DFS与BFS
#include<iostream>

using namespace std;

const int N = 10;
int path[N];
bool vis[N];
int n;

void dfs(int u)
{
    if(u == n) //&#x5230;&#x8FBE;&#x53F6;&#x5B50;&#x8282;&#x70B9;(&#x6570;&#x5B57;&#x586B;&#x5B8C;&#x4E86;)
    {
        for(int i = 0; i < n; i++) cout<<path[i]<<" "; cout<<endl; } 枚举所有方案 空位上可以选择的数字为:1 ~ n for(int i="1;" <="n;" i++) { if(!vis[i]) 没有被访问过 path[u]="i;" vis[i]="1;" 数字被使用,状态修改 dfs(u + 1); 填下一位 (到达叶子节点要回溯时——恢复现场) 恢复现场 int main() cin>>n;
    dfs(0);
    return 0;
}
</path[i]<<"></iostream>

n皇后问题

#include <iostream>
using namespace std;
const int N = 20;

// bool&#x6570;&#x7EC4;&#x7528;&#x6765;&#x5224;&#x65AD;&#x641C;&#x7D22;&#x7684;&#x4E0B;&#x4E00;&#x4E2A;&#x4F4D;&#x7F6E;&#x662F;&#x5426;&#x53EF;&#x884C;
// col&#x5217;&#xFF0C;dg&#x5BF9;&#x89D2;&#x7EBF;&#xFF0C;udg&#x53CD;&#x5BF9;&#x89D2;&#x7EBF;
// g[N][N]&#x7528;&#x6765;&#x5B58;&#x8DEF;&#x5F84;

int n;
char g[N][N];
bool col[N], dg[N], udg[N];

void dfs(int u) {
    // u == n &#x8868;&#x793A;&#x5DF2;&#x7ECF;&#x641C;&#x4E86;n&#x884C;&#xFF0C;&#x6545;&#x8F93;&#x51FA;&#x8FD9;&#x6761;&#x8DEF;&#x5F84;
    if (u == n) {
        for (int i = 0; i < n; i ++ ){
            for(int j = 0; j < n; j++){
                cout<<g[i][j]; } puts(""); 换行 return; 对n个位置按行搜索 for (int i="0;" < n; ++ ) 剪枝(对于不满足要求的点,不再继续往下搜索) udg[n - u + i],+n是为了保证下标非负 if (!col[i] && !dg[u i] !udg[n i]) { g[u][i]="Q" ; col[i]="dg[u" dfs(u 1); 恢复现场 这步很关键 int main() cin>> n;
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < n; j ++ )
            g[i][j] = '.';

    dfs(0);

    return 0;
}

</g[i][j];></iostream>

DFS迷宫问题(求解方案数)

无障碍物:

#include<iostream>
using namespace std;
int count,n;
bool st[100][100];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void dfs(int x,int y){
    if(x == n && y == n)
    {
        count ++;
        return ;
    }

    for(int i = 0; i <= 3; i++) 上下左右四个方向 { int ix="x" + dx[i]; iy="y" dy[i]; if(!st[ix][iy] &&>=1 && iy >= 1 && ix <= n && iy <="n)" { st[ix][iy]="true;" dfs(ix, iy); } int main(){ cin>>n;
    st[1][1] = true; // &#x8D77;&#x70B9;&#x6807;&#x8BB0;&#x4E3A;1
    dfs(1,1);
    cout<<count<<endl; return 0; } < code></count<<endl;></=></=></iostream>
#include<iostream>
using namespace std;
int count,n;
bool st[10][10];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int qx[100],qy[100];//&#x5B58;&#x5750;&#x6807;
void dfs(int x,int y,int u){//u&#x662F;&#x7B2C;&#x51E0;&#x6B65;
    if(x==n&&y==n){//&#x7ED3;&#x675F;&#x6761;&#x4EF6;
    count++; // &#x65B9;&#x6848;&#x6570;
//  for(int i=0;i<u;i++){ cout<<'('<<qx[i]<<','<<qy[i]<<')'; } return ; for(int i="0;i<=3;i++){//&#x679A;&#x4E3E;&#x6240;&#x6709;&#x53EF;&#x80FD;" 情况 int ix="x+dx[i];" iy="y+dy[i];" if(st[ix][iy]||ix<1||iy<1||ix>n||iy>n) continue;//&#x5224;&#x65AD;&#x5F53;&#x524D;&#x60C5;&#x51B5;&#x662F;&#x5426;&#x5408;&#x6CD5; &#x526A;&#x679D;
        qx[u]=ix;
        qy[u]=iy;
        st[ix][iy]=true;
        dfs(ix,iy,u+1);
        st[ix][iy]=false;//&#x6062;&#x590D;&#x73B0;&#x573A;

    }
}
int main(){
    cin>>n;
    st[1][1]=true;//&#x6CE8;&#xFF1A;&#x6807;&#x8BB0;&#x597D;
    qx[0]=1;
    qy[0]=1;
    dfs(1,1,1);
    cout<<count<<endl; return 0; } < code></count<<endl;></u;i++){></iostream>

有障碍物:

DFS与BFS
#include<iostream>
using namespace std;

bool st[100][100]; // &#x6807;&#x8BB0;&#x4F4D;&#x7F6E;&#x662F;&#x5426;&#x88AB;&#x7528;&#x8FC7;
bool map[100][100]; // &#x6807;&#x8BB0;&#x969C;&#x788D;&#x7269;

// &#x4E0A;&#x4E0B;&#x5DE6;&#x53F3;&#x56DB;&#x4E2A;&#x65B9;&#x5411;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};

int count; // &#x8BA1;&#x6570;
int n, m, t;
int sx, sy, fx, fy; // &#x8D77;&#x70B9;&#x7EC8;&#x70B9;&#x5750;&#x6807;&#xFF1A;(sx,sy)(fx,fy)

void dfs(int x,int y){
    if(x == fx && y == fy)
    {
        count ++;
        return ;
    }

    for(int i = 0; i <= 3; i++) 上下左右四个方向 { int ix="x" + dx[i]; iy="y" dy[i]; if(!st[ix][iy] && !map[ix][iy]>=1 && iy >= 1 && ix <= n && iy <="m)" { st[ix][iy]="true;" dfs(ix, iy); } int main(){ cin>> n>> m>> t>> sx>> sy>> fx>> fy;
    while(t --) // &#x8F93;&#x5165;&#x969C;&#x788D;&#x7269;
    {
        int x, y;
        cin>>x >> y;
        map[x][y] = true; // &#x969C;&#x788D;&#x7269;&#x4F4D;&#x7F6E;&#x6807;&#x8BB0;&#x4E3A;1
    }
    st[1][1] = true; // &#x8D77;&#x70B9;&#x6807;&#x8BB0;&#x4E3A;1
    dfs(1,1);
    cout<<count<<endl; return 0; } < code></count<<endl;></=></=></iostream>

单词方阵

单词接龙

加分二叉树

虫食算

BFS

最短路问题:宽搜的优势是能找到最短(最小)路!( 所有边权重都一样才可以用!)——一层一层的搜索(类似于树的层次遍历)。深搜可以保证我们走到终点,但不能确保是最短路。

搜索过程(层次遍历)如下:

(1)从图中的某个顶点出V发,访问V

(2)依次访问V的各个未曾访问过的邻接点

(3)分别从这些邻接点出发依次访问它们的邻接点,并使 “先被访问的顶点的邻接点”先于 “后被访问的顶点的邻接点”被访问

(4)重复步骤(3)直至所有已被访问的顶点的邻接点都被访问到

DFS与BFS

图的BFS和树几乎一模一样,唯一的区别是树有根节点,而图没有,因此在遍历图时要选一个根节点。下图以A作为根节点:

DFS与BFS

D和E是不能颠倒过来的,因为我们先遍历到的顶点是B,下一次展开的时候必须找与B直接相连的节点,即必须在找与C相连的节点之前把所有与B相连的节点找出来,由于A和C都走过了,因此唯一能走的点就是D。因此B先走完!

DFS与BFS

BFS的数据结构实现形式是队列,通过队列保存已被访问过的节点,利用其先进先出的特点: 保证了先访问的顶点的邻接点亦先被访问

即队列保证了下图中B的邻接点比C的邻接点要先出现:

DFS与BFS

填涂颜色

马的遍历

走迷宫(acwing 844)

给定一个 n×mn×m 的二维整数数组,用来表示一个迷宫,数组中只包含 00 或 11,其中 00 表示可以走的路,11 表示不可通过的墙壁。
最初,有一个人位于左上角 (1,1)(1,1) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角 (n,m)(n,m) 处,至少需要移动多少次。
数据保证 (1,1)(1,1) 处和 (n,m)(n,m) 处的数字为 00,且一定至少存在一条通路。
输入格式
第一行包含两个整数 nn 和 mm。
接下来 nn 行,每行包含 mm 个整数(00 或 11),表示完整的二维数组迷宫。
输出格式
输出一个整数,表示从左上角移动至右下角的最少移动次数。
数据范围
1≤n,m≤1001≤n,m≤100
输入样例:

5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出样例:

8

【参考代码】

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

using namespace std;

typedef pair<int, int> PII; // &#x7528;pair&#x6765;&#x5B58;&#x50A8;&#x5750;&#x6807;

const int N = 110;
// g[N][N]&#x521D;&#x59CB;&#x5316;&#x8F93;&#x5165;&#x6570;&#x636E;, d[N][N]&#x5F53;&#x524D;&#x4F4D;&#x7F6E;&#x5230;&#x539F;&#x70B9;&#x7684;&#x8DDD;&#x79BB;
int g[N][N], d[N][N];
// &#x4E0B;&#x4E00;&#x4E2A;&#x8282;&#x70B9;&#x53EF;&#x80FD;&#x7684;&#x4F4D;&#x7F6E;
 int dx[4] = {-1, 0, 1, 0};
 int dy[4] = {0, 1, 0, -1};
int n, m;

int bfs()
{
    queue<pii> q; // &#x961F;&#x5217;&#x5B58;&#x50A8;&#x8BBF;&#x95EE;&#x8FC7;&#x7684;&#x70B9;&#x5DF2;&#x7ECF;&#x8BE5;&#x9876;&#x70B9;&#x7684;&#x90BB;&#x63A5;&#x70B9;
    memset(d, -1, sizeof d); // &#x8DDD;&#x79BB;&#x521D;&#x59CB;&#x5316;&#x4E3A;- 1&#x8868;&#x793A;&#x6CA1;&#x6709;&#x8D70;&#x8FC7;
    d[0][0] = 0;
    q.push({0,0}); // &#x5F00;&#x59CB;&#x65F6;&#x6839;&#x8282;&#x70B9;&#x5148;&#x5165;&#x961F;

    while(q.size())
    {
        auto t = q.front(); // t&#x6307;&#x5411;&#x961F;&#x5934;&#x5143;&#x7D20;(&#x961F;&#x9996;&#x5143;&#x7D20;&#x8FD8;&#x6709;&#x7528;)
        q.pop(); // &#x961F;&#x5934;&#x5143;&#x7D20;&#x51FA;&#x961F;

        // &#x679A;&#x4E3E;&#x51FA;&#x961F;&#x7684;&#x961F;&#x9996;&#x5143;&#x7D20;&#x7684;&#x6240;&#x6709;&#x90BB;&#x63A5;&#x70B9;
        for(int i = 0; i < 4; i ++)
        {
            int x = t.first + dx[i];
            int y = t.second + dy[i];
            // d[x][y] == -1 &#x8868;&#x793A;&#x8BE5;&#x4F4D;&#x7F6E;&#x8FD8;&#x6CA1;&#x88AB;&#x8BBF;&#x95EE;&#x8FC7;
            if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
            {
                d[x][y] = d[t.first][t.second] + 1; // &#x8DDD;&#x79BB;&#x52A0;1
                q.push({x, y}); // &#x90BB;&#x63A5;&#x70B9;&#x5165;&#x961F;
            }

        }
    }

    // &#x8D70;&#x51FA;&#x8FF7;&#x5BAB;&#x8FD4;&#x56DE;&#x7B54;&#x6848;
    return d[n -1][m - 1];
}

int main()
{
    cin>>n >>m;
    // &#x521D;&#x59CB;&#x5316;&#x8FF7;&#x5BAB;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
            cin>>g[i][j];

    cout<<bfs(); return 0; } < code></bfs();></pii></int,></queue></algorithm></cstring></iostream>

数组模拟队列:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 110;
typedef pair<int, int> PII;
int n, m;
int g[N][N];//&#x5B58;&#x653E;&#x5730;&#x56FE;
int d[N][N];//&#x5B58; &#x6BCF;&#x4E00;&#x4E2A;&#x70B9;&#x5230;&#x8D77;&#x70B9;&#x7684;&#x8DDD;&#x79BB;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};//x &#x65B9;&#x5411;&#x7684;&#x5411;&#x91CF;&#x548C; y &#x65B9;&#x5411;&#x7684;&#x5411;&#x91CF;&#x7EC4;&#x6210;&#x7684;&#x4E0A;&#x3001;&#x53F3;&#x3001;&#x4E0B;&#x3001;&#x5DE6;
PII q[N * N];//&#x624B;&#x5199;&#x961F;&#x5217;
int bfs()
{
    int hh = 0, tt = 0;
    q[0] = {0, 0};

    memset(d, - 1, sizeof d);//&#x8DDD;&#x79BB;&#x521D;&#x59CB;&#x5316;&#x4E3A;- 1&#x8868;&#x793A;&#x6CA1;&#x6709;&#x8D70;&#x8FC7;

    d[0][0] = 0;//&#x8868;&#x793A;&#x8D77;&#x70B9;&#x8D70;&#x8FC7;&#x4E86;

    while(hh <= tt) 队列不空 { pii t="q[hh" ++ ]; 取队头元素 for(int i="0;" < 4; ) 枚举4个方向 int x="t.first" + dx[i], y="t.second" dy[i]; x表示沿着此方向走会走到哪个点 if(x>= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)//&#x5728;&#x8FB9;&#x754C;&#x5185; &#x5E76;&#x4E14;&#x662F;&#x7A7A;&#x5730;&#x53EF;&#x4EE5;&#x8D70; &#x4E14;&#x4E4B;&#x524D;&#x6CA1;&#x6709;&#x8D70;&#x8FC7;
            {
                d[x][y] = d[t.first][t.second] + 1;//&#x5230;&#x8D77;&#x70B9;&#x7684;&#x8DDD;&#x79BB;
                q[ ++ tt ] = {x, y};//&#x65B0;&#x5750;&#x6807;&#x5165;&#x961F;
            }
        }
    }
    return d[n - 1][m - 1]; //&#x8F93;&#x51FA;&#x53F3;&#x4E0B;&#x89D2;&#x70B9;&#x8DDD;&#x8D77;&#x70B9;&#x7684;&#x8DDD;&#x79BB;&#x5373;&#x53EF;
}
int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++ )
        for(int j = 0; j < m; j ++ )
            cin >> g[i][j];

    cout << bfs() << endl;

    return 0;
}
</=></int,></algorithm></cstring></iostream>

奇怪的电梯

字符串变换

机器人搬重物

memset()函数的使用

  1. memset()函数原型是:
extern void *memset(void *buffer, int c, int count)

  //buffer:为指针或是数组,

  //c:是赋给buffer的值,

  //count:是buffer的长度.

这个函数在socket中多用于清空数组.如:原型是:

memset(buffer, 0, sizeof(buffer))

2.memset 用来对一段内存空间(数组)进行初始化;

int arr[N][N];

memset(arr, -1, sizeof(arr));

注:memset()可以初始化整数数组,但是初始化的值只能为0或者-1。

Original: https://www.cnblogs.com/lwtyyds/p/15542379.html
Author: 时间最考验人
Title: DFS与BFS

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/584071/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球