一:BFS和DFS
- 两者之间关于最短性和不具有最短性的区别,从顶点到最左下角的顶点,如果是BFS因为那条边的加入,最短路径是2,DFS的是4
- DFS的空间复杂度很明显是树的高度决定,对于BFS很明显就是根据树的宽度决定的。

DFS的核心:递归边界,访问,递归循环,还原
二:DFS输出全排列
#include <iostream>using namespace std;const int N = 10; // 题目要求的int n;int path[N], st[N]; // path存储的实际输出的内容, st存储已经被使用的点void dfs(int s){if (s > n) // 这里根据main中dfs()传入的值确定{for (int i = 1; i <= n; i++) // dfs传入的初始值是0,i就需要从0开始遍历,因为传入的是1,从1开始遍历cout << path[i] << " ";cout << endl;return;}for (int i = 1; i <= n; i++) // 遍历所有的数字,看哪些数字没有使用过。{if (!st[i]) // st的作用就是看哪些没有用到{path[s] = i; // 注意下标是传入的s不是ist[i] = 1; // 用1标识这个数字已经用过了dfs(s + 1); // 下一位的选择st[i] = 0; // 回溯过程的体现,还原,path不用还原因为path就会被覆盖}}}int main(){ios::sync_with_stdio(false);cin >> n;dfs(1);return 0;}
三:DFS之N-皇后问题


首先弄清楚,如果使用下标从0开始,输出的时候不能用puts(p[i]),因为输出总是有问题,puts输出没办法控制二维,只能傻瓜式输出一维,而且puts括号内只能是指针或者数组名,puts输出的内容只要遇到/0的时候就输出错误,这也是如果初始化的时候,如果只初始化二维的第二个元素,0号位置的不管,通过puts的时候输出失败的原因。
- 还要注意的就是斜线跟横纵坐标的关系,跟下标从什么开始也不太一样,反斜线也是有一定关系的(下标0开始:列+ n - 行 )。
- 本质的递归边界,访问,递归,还原没有变,但是传递的起始值是发生变化的
#include <iostream>using namespace std;const int N = 20; // 斜对角线的数目是行、列的 2n - 1char g[N][N];bool col[N], dg[N], udg[N]; // col记录列占用,dg记录\对角线,udg记录/对角线int n;void dfs(int u){if (u == n){for (int i = 0; i < n; i++) puts(g[i]); // 可以通过输出一维元素输出内容puts("");return;}for (int i = 0; i < n; i++){if (!col[i] && !dg[i + u] && !udg[i - u + n]) // 当前列,斜线,反斜线全部都没有被占用{col[i] = dg[i + u] = udg[i - u + n] = true;g[u][i] = 'Q';dfs(u + 1);col[i] = dg[i + u] = udg[i - u + n] = false;g[u][i] = '.';}}}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;}
四:BFS
- 迷宫问题如果使用深度优先搜索的话,能保证搜到,但是不能保证搜到的路径是最短的。
- 需要注意BFS虽然可以解决最短路,但是局限性在于只能解决所有边权都是1的时候

- memset的初始化

- 基本思路就是把g图中所有的0的点依次放入队列q中,然后计算出每个点到起点的距离,因为最终只需要最右下角的点,所以只需要返回d[n - 1][m - 1];
#include <iostream>#include <cstring>using namespace std;typedef pair<int, int> PII; // 用来存储x, yconst int N = 110;int g[N][N], d[N][N]; // g存储整个图形,d存储图中为0的点到原点的距离PII q[N * N]; // 作为队列,一次放入所有的0的点,计算距离int n, m;int bfs(){int hh = 0, rr = 0;memset(d, -1, sizeof d); // memset初始化的时候,sizeof d就是按照d一个元素大小初始化,最小是字节d[0][0] = 0; // 起始点距离肯定是0q[0] = {0, 0}; 队列自然存储的是第一个点的坐标int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1}; // 某个点上下左右四个点的坐标while (hh <= rr){auto u = q[hh++];for(int i = 0; i < 4; i++){int x = u.first + dx[i], y = u.second + dy[i];if (x >= 0 && x < n && y >= 0 && y < m && d[x][y] == -1 && g[x][y] == 0) // 前四个条件不能越界,后面是g必须是0,而且距离是没有被计算{d[x][y] = d[u.first][u.second] + 1;q[++rr] = {x, y};}}}return d[n - 1][m - 1];}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;}
