这是我的第一道dfs题 相比于bfs 我对利用递归的dfs理解的没有那么透彻
下面代码是我自己写出来 根据gpt修改意见AC出来的
#include <bits/stdc++.h>
using namespace std;
int checkedboard[1002][1002]; // 棋盘储存棋子
bool visited[1002][1002]; // 记录访问状态
int n, m;
int turn_point = 0;
int x11, y11, x22, y22;
// 检查位置是否合法
bool checked(int x, int y) {
if (x >= 0 && x < n && y >= 0 && y < m && (checkedboard[x][y] == 0||x==x22&&y==y22) && !visited[x][y])
return true;
return false;
}
// 方向数组
int directions[4][2] = {
{0, 1},
{0, -1},
{1, 0},
{-1, 0}
};
// 深度优先搜索
bool DFS(int x1, int y1, int x2, int y2, int turn, int current_dir) {
if (x1 == x2 && y1 == y2)
return true;
visited[x1][y1] = true; // 标记当前位置已访问
for (int i = 0; i < 4; i++) {
int newx1 = x1 + directions[i][0];
int newy1 = y1 + directions[i][1];
if (checked(newx1, newy1)) {
// 计算新的转折次数
int new_turn = (i == current_dir) ? turn : turn + 1;
if (new_turn <= 2) { // 假设转折次数的限制是2
if (DFS(newx1, newy1, x2, y2, new_turn, i)) {
return true;
}
}
}
}
visited[x1][y1] = false; // 取消标记,回溯
return false;
}
int main() {
while (cin >> n >> m) {
if (n == 0 && m == 0) break;
memset(checkedboard, 0, sizeof(checkedboard));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> checkedboard[i][j];
}
}
int q;
cin >> q;
while (q--) {
cin >> x11 >> y11 >> x22 >> y22;
x11--; y11--; x22--; y22--; // 转换为0索引
if ((checkedboard[x11][y11] == checkedboard[x22][y22]) && checkedboard[x11][y11] != 0) {
memset(visited, false, sizeof(visited));
if (DFS(x11, y11, x22, y22, -1, -1)) {
cout << "YES\n";
}
else {
cout << "NO\n";
}
}
else {
cout << "NO\n";
}
}
}
return 0;
}
说一下我忽略的几个点:
1.本题关键是我利用转折次数
初始值要设为-1 因为第一次四个方向都不算转折
2.我忘记了visited数组 这是关键
在checked中利用visited检查是否被访问过
这里要注意进行回溯因为当我们递归返回的时候代表另一种思路需要取消标记
3.bool类型的dfs函数:一种return的思想
当我dfs时候需要if(dfs())return true;否则不会返回
4.全局变量y1和math中的变量重名需要更改名字