算法基础课——第三章 搜索与图论(一)

这篇博客介绍了搜索与图论的基础知识,包括DFS(深度优先搜索)和BFS(广度优先搜索)的区别与联系。通过实例展示了DFS和BFS在排列数字、n-皇后问题、走迷宫等场景的应用。强调了BFS适用于找最短路径的情况,而DFS则常用于解决复杂问题和避免额外空间。文中还提到了树与图的存储、遍历方法以及拓扑排序的概念。
摘要由CSDN通过智能技术生成
image-20210807031457384

第三章 搜索与图论(一)


DFS与BFS的区别与联系

  1. 都可以对整个问题空间进行遍历;
  2. 搜索的结构都像树一样;
  3. 但搜索的顺序是不同的;
  4. 深度优先搜索是尽可能往深里搜,当搜到叶子节点的时候回溯;
  5. D F S DFS DFS 就像一个非常执着的人,它会不断往深里搜,搜到头后回去的时候也还不是直接回到头,而是边回去边看能不能继续往前走,只有确定当前点所有路都走不了的时候,才会往回退一步;

下图中的树代表整个问题空间,节点上的数字代表 D F S DFS DFS 遍历的顺序:

image-20210807031457384
DFS遍历顺序图示
  1. B F S BFS BFS 比较像眼观六路耳听八方(稳重)的人,它搜索时是一层一层地搜的,它可以同时看很多条路,它每次只会扩展一层,只有当前层扩展完后,才会去扩展下一层;

下图中的树代表整个问题空间,节点上的数字代表 B F S BFS BFS 遍历的顺序:

image-20210807031457384
BFS遍历顺序图示
数据结构 空间
D F S DFS DFS s t a c k stack stack(栈) O ( h ) O(h) O(h)​ , h h h表示树的深度 不具最短性
B F S BFS BFS q u e u e queue queue(队列) O ( 2 h ) O(2^h) O(2h)​, h h h表示树的层数 “最短路”

由于 B F S BFS BFS​​搜索时是一层一层往外扩展的,所以它第一次搜到的点一定是离它最近的点,因此它有一个最短路的概念.

例如下图情况,相同的点, D F S DFS DFS​​ 搜索到时( 5 5 5​​ 号点)就认为其距离根节点( 1 1 1 ​​号点)为 4 4 4​​,而 B F S BFS BFS​​ 搜索到时( 4 4 4​​号点)就认为其距离根节点( 1 1 1​​号点)为 2 2 2.​

image-20210807031457384
如果多加了一条边,则DFS与BFS的遍历顺序不同

Q: B F S BFS BFS 一般都是最短路吗?
A:不是,但当一个图的所有的权重都是 1 1 1 的时候, B F S BFS BFS搜到的一定是最短路,因为扩展时是先把所有距离其为 1 1 1 的点扩展进来,再把距离其为 2 2 2的点扩展进来,所以它是一层一层的,扩展的距离也是逐渐递增的,所以第一次扩展到的点一定是最近的点。凡是涉及到“最小步数”、“最短距离”、“最少操作几次“基本上都是 B F S BFS BFS;算法思路比较奇怪的或者对空间要求比较高的,一般都用 D F S DFS DFS.

Q: D F S DFS DFS 是递归吗?
A: D F S DFS DFS 其实就是递归,没必要把 D F S DFS DFS 和递归区分得太开.

Q:所以写 D F S DFS DFS 的时候要存为一棵树吗?
A:存的时候每次只会存当前这条路径,所以不需要把整棵树存下来,而且也不需要真的把栈写出来,系统会帮我们做回溯的,它有隐藏的栈来维护这个路径,不需要开额外的空间.


深度优先搜索 DFS


D F S DFS DFS 中有两个重要的概念:回溯剪枝.
每一个 D F S DFS DFS 都对应一棵搜索树.

AcWing 842. 排列数字

原题链接

给定一个整数 n n n,将数字 1 ∼ n 1\sim n 1n 排成一排,将会有很多种排列方法。

现在,请你按照字典序将所有的排列方法输出。

输入格式

共一行,包含一个整数 n n n

输出格式

按字典序输出所有排列方案,每个方案占一行。

数据范围

1 ≤ n ≤ 7 1≤n≤7 1n7

输入样例:

3

输出样例:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

时/空限制: 1s / 64MB
来源: 模板题
算法标签:dfs

yxc’s Solution

  • 如何用 D F S DFS DFS 来做这道题?

  • D F S DFS DFS 最重要的需要考虑的地方是 顺序

  • D F S DFS DFS 对应的搜索顺序可以看作是一个 的形式:

    1. 假设一开始有 n n n 个空位;

    2. 顺序 是 从第一位开始填,从前往后一位一位地填。每次填的时候 填的数字不能和前面一样;

    3. 可以得到搜索树如下:

image-20210807031457384
搜索树图示

回溯 指的是 D F S DFS DFS 到叶子节点时,往回走的过程.
回溯中一定要注意一点:恢复现场.

#include<iostream>
using namespace std;
const int N=10;
int n;
int path[N];//储存路径
bool st[N]; //储存状态(某个数是否被用过)
void dfs(int u)
{
   
    if(u==n)
    {
   
        for(int i=0;i<n;i++) printf("%d ",path[i]);
        puts("");
        return;
    }
    for(int i=1;i<=n;i++)
        if(!st[i])
        {
   
            path[u]=i;
            st[i]=true;
            dfs(u+1);
            st[i]=false;//恢复现场
        }
}
int main()
{
   
    cin>>n;
    dfs(0);
    return 0;
}

AcWing 843. n-皇后问题

原题链接

n n n−皇后问题是指将 n n n 个皇后放在 n × n n \times n n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

image-20210807031457384

现在给定整数 n n n,请你输出所有的满足条件的棋子摆法。

输入格式

共一行,包含整数 n n n

输出格式

每个解决方案占 n n n 行,每行输出一个长度为 n n n 的字符串,用来表示完整的棋盘状态。

其中 . 表示某一个位置的方格状态为空,Q 表示某一个位置的方格上摆着皇后。

每个方案输出完成后,输出一个空行。

注意:行末不能有多余空格。

输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围

1 ≤ n ≤ 9 1≤n≤9 1n9

输入样例:

4

输出样例:

.Q..
...Q
Q...
..Q.

..Q.
Q...
...Q
.Q..

时/空限制: 1s / 64MB
来源: 模板题,AcWing
算法标签:dfs 剪枝

yxc’s Solution1

  • 顺序:从前往后看每一行,枚举每一行,看皇后放到哪一个列上.
  • 剪枝:当前位置要枚举某一个数时,直接判断其有没有冲突,有冲突就没必要往下走了.
  • 时间复杂度: O ( n × n ! ) O(n \times n!) O(n×n!).

这种方法保证了枚举时每行只有一个皇后.
剪枝 是指判断当前方案不合法后,就没有必要往下搜了,就相当于把子树剪掉,直接回溯.

对于 d g [ ] dg[] dg[],次对角线在直角坐标系上可以写成 y =

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值