// 初始化队列,存入起始状态
queue<数据类型> q;
q.push(初始状态);
标记初始状态为已访问;
while (!q.empty()) {
// 队列非空表示还有待访问节点
取出队头节点并弹出; // 读取当前待处理节点
枚举当前节点的所有可达状态/相邻节点;
for (每个可达状态 v) {
if (v 合法且未被访问) {
// 筛选合法未访问节点
标记 v 为已访问; // 立即标记,避免重复入队
q.push(v); // 合法节点入队,等待后续处理
按需更新结果/状态;
}
}
}
4. 算法适用场景
无权图最短路径、层级遍历、区域统计等需要按距离/层级推进的场景。
四、题目与题解
(一)组合的输出(基础 DFS 例题)
题目描述
题解代码
#include<bits/stdc++.h>usingnamespace std;
int n, m;
vector<int> chosen;
voiddfs(int x){
// 剪枝操作:减少无效递归,提升效率if (chosen.size() > m || chosen.size() + n - x + 1 < m) return;
if (chosen.size() == m) {
for (int i = 0; i < chosen.size(); i++) {
cout << setw(3) << chosen[i];
}
puts("");
return;
}
// 第一种选择:选取当前数字 x
chosen.push_back(x);
dfs(x + 1);
chosen.pop_back();
// 第二种选择:不选取当前数字 xdfs(x + 1);
}
intmain(){
cin >> n >> m;
dfs(1);
return0;
}
#include<bits/stdc++.h>usingnamespace std;
constint N = 1010;
char g[N][N];
int n = 30;
int m = 60;
int dx[4] = {0, 1, -1, 0};
int dy[4] = {1, 0, 0, -1};
intdfs(int x, int y){
if (g[x][y] == '0') return0;
g[x][y] = '0';
int ans = 1;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
ans += dfs(nx, ny);
}
return ans;
}
intmain(){
for (int i = 0; i < n; i++) {
cin >> g[i];
}
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (g[i][j] == '1') {
ans = max(ans, dfs(i, j));
}
}
}
cout << ans;
return0;
}
#include<iostream>#include<queue>#include<string>usingnamespace std;
constint N = 25;
char g[N][N];
int n, m;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
structnode {
int x, y;
};
intbfs(int sx, int sy){
int res = 0;
queue<node> q;
q.push({sx, sy});
g[sx][sy] = '#';
while (q.size()) {
node tmp = q.front();
q.pop();
res++;
for (int i = 0; i < 4; i++) {
int x = tmp.x + dx[i];
int y = tmp.y + dy[i];
if (x < 0 || x >= n || y < 0 || y >= m || g[x][y] == '#') continue;
q.push({x, y});
g[x][y] = '#';
}
}
return res;
}
intmain(){
while (cin >> m >> n && (m | n)) {
for (int i = 0; i < n; i++) cin >> g[i];
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (g[i][j] == '@') ans = bfs(i, j);
}
}
cout << ans << endl;
}
return0;
}
(四)路径之谜(DFS 剪枝进阶例题)
题目描述
小明冒充 XX 星球的骑士,进入了一个奇怪的城堡。城堡里边什么都没有,只有方形石头铺成的地面。假设城堡地面是 n×n 个方格。按习俗,骑士要从西北角走到东南角。可以横向或纵向移动,但不能斜着走,也不能跳跃。每走到一个新方格,就要向正北方和正西方各射一箭。(城堡的西墙和北墙内各有 n 个靶子)同一个方格只允许经过一次。但不必走完所有的方格。如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?
本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)。
输入描述
第一行一个整数 N (0≤N≤20),表示地面有 N×N 个方格。
第二行 N 个整数,空格分开,表示北边的箭靶上的数字(自西向东)。
第三行 N 个整数,空格分开,表示西边的箭靶上的数字(自北向南)。
#include<bits/stdc++.h>usingnamespace std;
int n;
int s[1000];
int z[1000];
int res[100000];
int book[100][100];
int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
voiddfs(int x, int y, int dep, int s[], int z[], int &tep){
if (tep == 1) return;
if (x == n - 1 && y == n - 1) {
for (int i = 0; i < n; i++) {
if (s[i] != 0 || z[i] != 0) return;
}
tep = 1;
for (int i = 0; i < dep; i++) printf("%d ", res[i]);
return;
}
for (int i = 0; i < 4; i++) {
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if (book[tx][ty] == 1 || tx < 0 || tx > n - 1 || ty < 0 || ty > n - 1 || s[ty] - 1 < 0 || z[tx] - 1 < 0) continue;
res[dep] = tx * n + ty;
book[tx][ty] = 1;
s[ty]--;
z[tx]--;
dfs(tx, ty, dep + 1, s, z, tep);
book[tx][ty] = 0;
s[ty]++;
z[tx]++;
}
return;
}
intmain(){
cin >> n;
for (int i = 0; i < n; i++) cin >> s[i];
for (int i = 0; i < n; i++) cin >> z[i];
book[0][0] = 1;
s[0]--;
z[0]--;
int tep = 0;
dfs(0, 0, 1, s, z, tep);
return0;
}