问题描述
小蓝最近迷上了一款名为《数字接龙》的迷宫游戏。
游戏在一个大小为 N × N
的格子棋盘上展开,其中每一个格子处都有一个 0
到 K-1
之间的整数。
游戏规则如下:
-
从左上角
(0, 0)
出发,目标是到达右下角(N-1, N-1)
。 -
每一步可以选择沿 水平、垂直或对角线 方向移动到下一个格子(共 8 个方向)。
-
路径经过的棋盘格子,其上面的数字必须按顺序组成如下循环序列:
0, 1, 2, ..., K-1, 0, 1, 2, ..., K-1, ...
-
途中需要对棋盘上的 每个格子恰好经过一次(仅一次)。
-
路径中不允许出现交叉线路。
例如:若曾从 (0,0)
移动到 (1,1)
,则不能再从 (1,0)
移动到 (0,1)
,因为这样会形成交叉。
为方便表示,我们对可以行进的所有八个方向编号如下
因此,行进路径可以用一个包含 0
到 7
的数字字符串来表示。
输入格式
第一行包含两个整数 N
和 K
,分别表示棋盘的边长和数字序列的周期长度。
接下来 N
行,每行 N
个整数,表示棋盘格子上的数字。
输出格式
输出一行表示答案路径,用方向编号组成的字符串表示。
- 如果存在多条合法路径,输出字典序最小的那一个;
- 如果不存在任何合法路径,输出
-1
。
样例输入
3 3
0 2 0
1 1 1
2 0 2
样例输出
41255214
样例说明
行进路径如图所示,路径编号为:4 → 1 → 2 → 5 → 5 → 2 → 1 → 4
。
评测用例规模与约定
- 对于 80% 的评测用例:
1 ≤ N ≤ 5
- 对于 100% 的评测用例:
1 ≤ N ≤ 10
,1 ≤ K ≤ 10
c++代码
#include<iostream>
#include<vector>
#include<string>using namespace std;int N, K;vector<vector<int>> arr;
vector<vector<vector<int>>> know;
string ans = "-1", mid;void dfs(int i, int j, int msg, string ops, int lasti, int lastj) {if (ans != "-1" || i < 0 || i >= N || j < 0 || j >= N || know[i][j][0] != -1 || arr[i][j] != msg) return;mid += ops;if (i > 0 || j > 0) know[lasti][lastj][0] = i, know[lasti][lastj][1] = j;if (mid.size() == N * N - 1 && i == N - 1 && j == N - 1) {ans = mid;return;}if (msg == K - 1) msg = 0;else msg++;dfs(i - 1, j, msg, "0", i, j);if (i - 1 >= 0 && j + 1 < N && !((know[i][j + 1][0] == i - 1 && know[i][j + 1][1] == j) || (know[i - 1][j][0] == i && know[i - 1][j][1] == j + 1))) dfs(i - 1, j + 1, msg, "1", i, j);dfs(i, j + 1, msg, "2", i, j);if (i + 1 < N && j + 1 < N && !((know[i][j + 1][0] == i + 1 && know[i][j + 1][1] == j) || (know[i + 1][j][0] == i && know[i + 1][j][1] == j + 1))) dfs(i + 1, j + 1, msg, "3", i, j);dfs(i + 1, j, msg, "4", i, j);if (i + 1 < N && j - 1 >= 0 && !((know[i][j - 1][0] == i + 1 && know[i][j - 1][1] == j) || (know[i + 1][j][0] == i && know[i + 1][j][1] == j - 1))) dfs(i + 1, j - 1, msg, "5", i, j);dfs(i, j - 1, msg, "6", i, j);if (i - 1 >= 0 && j - 1 >= 0 && !((know[i][j - 1][0] == i - 1 && know[i][j - 1][1] == j) || (know[i - 1][j][0] == i && know[i - 1][j][1] == j - 1))) dfs(i - 1, j - 1, msg, "7", i, j);if (mid.size() > 0) mid.erase(mid.size() - 1);if (i > 0 || j > 0) know[lasti][lastj][0] = -1, know[lasti][lastj][1] = -1;
}int main() {cin >> N >> K;arr = vector<vector<int>>(N, vector<int>(N));know = vector<vector<vector<int>>>(N, vector<vector<int>>(N, vector<int>(2, -1)));for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {cin >> arr[i][j];}}dfs(0, 0, 0, "", -1, -1);cout << ans;return 0;
}//by wqs
算法思路
这本质上是一道dfs搜索题
比较有难度的是如何保证不交叉
我们用一个三维数组vector<vector<vector<int>>> know;
know[i][j][0] = a, know[i][j][1] = b;
如果a == -1 && b == -1说明当前节点没有访问
否则存在一条从点(a, b)到(i,j)的有向连线。
我们根据这个数组的状态去判断是否有交叉