基础搜索
基础搜索
深度优先搜索(dfs, 栈实现)
dfs十分简单,不搜到最后不会往回走
只需要一个例题就可以整明白dfs是怎么应用的
全排列问题
给定一个n,输出n的全排列
分析:
每增加一个数字就向下搜到一个节点
我们从第一个开始搜,直到搜到第n个数字结束
搜的过程中记录搜过了那个数字,之后就不能搜这个数字
代码实现:
#include <iostream> using namespace std; const int N = 10; int n; int val[N]; bool vis[N]; void dfs(int u) { if (u == n) { for (int i = 0; i < n; i ++ ) printf(" %d", val[i]); printf("\n"); return; } for (int i = 1; i <= n; i ++ ) if (!vis[i]) { val[u] = i; vis[i] = true; dfs(u + 1); // 恢复现场 vis[i] = false; val[u] = 0; } } int main() { scanf("%d", &n); dfs(0); return 0; }
n皇后问题
[八皇后](P1219 [USACO1.5]八皇后 Checker Challenge - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))
思路:
这是一个经典的dfs题
dfs的每个节点存的是每一层的棋子放到哪
还要额外开col, dg, udg这几个数组分别来存这一列,这个对角线,反对角线是否有棋子
代码实现:
#include <iostream> using namespace std; const int N = 30; int n, tot; int e[N]; bool col[N], dg[N], udg[N]; void dfs(int u) { if (u == n) { tot ++ ; if (tot <= 3) { for (int i = 0; i < n; i ++ ) printf("%d ", e[i]); printf("\n"); } return; } for (int i = 0; i < n; i ++ ) if (!col[i] && !dg[u + i] && !udg[n - u + i]) { e[u] = i + 1; col[i] = dg[u + i] = udg[n - u + i] = true; dfs(u + 1); col[i] = dg[u + i] = udg[n - u + i] = false; } } int main() { scanf("%d", &n); dfs(0); printf("%d\n", tot); return 0; }
第二种做法:
这种方法思路简单,每一个地方可以选择选或不选,分别递归
代码:
// 时间复杂度较高,会有几个点tle #include <iostream> using namespace std; const int N = 30; int n, cnt, tot; int e[N]; bool col[N], row[N], dg[N], udg[N]; void dfs(int x, int y, int s) { if (y == n) y = 0, x ++ ; if (x == n) { if (s == n && cnt < 3) { for (int i = 0; i < n; i ++ ) printf("%d ", e[i] + 1); printf("\n"); cnt ++ ; } if (s == n) tot ++ ; return; } // 放棋子 if (!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n]) { e[x] = y; row[x] = col[y] = dg[x + y] = udg[x - y + n] = true; dfs(x, y + 1, s + 1); row[x] = col[y] = dg[x + y] = udg[x - y + n] = false; e[x] = 0; } // 不放棋子 dfs(x, y + 1, s); } int main() { scanf("%d", &n); dfs(0, 0, 0); printf("%d", tot); return 0; }
宽度优先搜索(bfs, 队列实现)
宽度搜索比较沉稳,一层一层搜
因为bfs的搜索顺序,它具有最短路的性质,
如果有环的话,第一次搜到这个点的路径就是最短路
例题:
[马的遍历](P1443 马的遍历 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))
bfs有一个技巧,搜下一个节点的时候不需要写很多个if
直接用一个向量来存
#include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; typedef pair<int, int> PII; const int N = 410; int n, m, x, y; vector<PII> q; int d[N][N]; void bfs() { memset(d, -1, sizeof d); d[x][y] = 0; q.push_back({x, y}); int dx[8] = {1, 2, 2, 1, -1, -2, -2, -1}; int dy[8] = {2, 1, -1, -2, 2, 1, -1, -2}; int hh = 0, tt = 0; while (hh <= tt) { auto t = q[hh ++ ]; for (int i = 0; i < 8; i ++ ) { int a = t.first + dx[i], b = t.second + dy[i]; if (a >= 1 && a <= n && b >= 1 && b <= m && d[a][b] == -1) { d[a][b] = d[t.first][t.second] + 1; q.push_back({a, b}); tt ++ ; } } } } int main() { scanf("%d%d%d%d", &n, &m, &x, &y); bfs(); for (int i = 1; i <= n; i ++ ) { for (int j = 1; j <= m; j ++ ) printf("%-5d", d[i][j]); printf("\n"); } return 0; }
本文作者:张詠然
本文链接:https://www.cnblogs.com/zyrddd/p/16595122.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步