标签:arc https struct new alt 扫描 NPU str false
骑士按照下图所示的走法对棋盘进行巡逻,每个格子只允许巡逻一次,且必须巡逻所有格子。给定棋盘的行数p和列数q,输出一条骑士巡逻路径,若不存在这样一条路径,则输出impossible。
3
1 1
2 3
4 3
Scenario #1:
A1
Scenario #2:
impossible
Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4
深度优先搜索(Depth-First Search,DFS)算法,伪代码如下\(^{[2]}\):
1个WA点:若存在多条巡逻路径,题目要求输出字典序优先的路径,lexicographically first path。也就是说,假如A1B1C1和A1C1B1都是允许的路径,则选择A1B1C1,因为B在C前面。其实这一点挺好实现,只需要从左往右扫描“列”即可保证字典序优先。
Result: 372kB, 0ms.
#include <stdio.h>
#include <string.h>
#include <vector>
int n, p, q;
int delta_row[8] = { -1, 1, -2, 2, -2, 2, -1, 1 };//DFS的搜索顺序,按照列从左往右的顺序进行搜索。
int delta_col[8] = { -2, -2, -1, -1, 1, 1, 2, 2 };//即搜索的优先级(-1, -2)=(1, -2)>(-2, -1)=(2, -1)>(-2, 1)=(2, 1)>(-1, 2)=(1, 2),等于的意思是先搜索哪一个不影响字典序
int explored[30][30];//标记是否为已搜索过的节点
int cnt;
struct Node {
int row, col;
} path[30];//记录下路径
void Init() {
memset(explored, 0, sizeof(explored));
cnt = 0;
}
bool Dfs(int row, int col) {
explored[row][col] = 1;//标记为已搜索的节点
cnt++;//深度加1
path[cnt].row = row;
path[cnt].col = col;
for (int i = 0; i < 8; i++) {//按照列从左往右的顺序进行搜索
int row_new = row + delta_row[i], col_new = col + delta_col[i];
if (row_new >= 1 && row_new <= p && col_new >= 1 && col_new <= q && !explored[row_new][col_new]) {//骑士要去巡逻的新节点(row_new, col_new)在棋盘范围内且未搜索过
if (Dfs(row_new, col_new))//若找到路径,直接break,一层层跳出递归,若没找到,对下一个优先级的要去巡逻的新节点进行搜索
break;
}
}
if (cnt == p * q)//若深度为p*q,说明我们找到了路径
return true;
else {//若没找到,回溯到前一节点,当前节点置为未搜索的节点,树的深度减1
explored[row][col] = 0;
cnt--;
return false;
}
}
int main() {
scanf("%d", &n);
for (int t = 1; t <= n; t++) {
scanf("%d %d", &p, &q);
printf("Scenario #%d:\n", t);
Init();
if (Dfs(1, 1)) {
for (int i = 1; i <= p * q; i++)
printf("%c%c", 'A' + path[i].col - 1, '1' + path[i].row - 1);
printf("\n");
}
else
printf("impossible\n");
if (t != n)
printf("\n");
}
return 0;
}
[1] Knight‘s tour
[2] 算法设计
标签:arc https struct new alt 扫描 NPU str false
原文地址:https://www.cnblogs.com/wtyuan/p/12106652.html