本题是DFS问题,注释里有比较详细的分析。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int a[100][100];//记录题目给的数组
int dt[8][2] = { {-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1} };//记录方向,向下是x轴,向右是y轴
int K;//行、列数
vector<int>path;//记录单个路径
vector<vector<int>>res;//记录所有路径
bool vis[100][100] = { false };//判断该点是否被遍历过
void DFS(int x, int y) {
if (path.size() == K * K - 1 && x == K - 1 && y == K - 1) {//如果所有点都被遍历完了,那么路径的长度就为K*K-1,x和y的位置就为K-1
res.push_back(path);
return;
}
vis[x][y] = true;
for (int i = 0; i < 8; i++) {//判断该点的八个方向
int sx = dt[i][0];
int sy = dt[i][1];
int tx = x + sx;//记录下一步的x位置
int ty = y + sy;//记录下一步的y位置
if (tx >= 0 && tx < K && ty >= 0 && ty < K && vis[tx][ty] == false && a[tx][ty] == (a[x][y] + 1) % K) {//不能超出边界且下一步位置(tx,ty)未被访问,下一步的位置(tx,ty)就为当前位置(x,y)+1%K
if (vis[tx][y] && vis[x][ty]) {//判断是否交叉,交叉的情况就是:与当前位置到下一步位置邻接的两个点被访问过。(下面用注释表示了一下)
//当前位置(x,y) 邻接点1(vis[]==true)
//邻接点2(vis[]==true) 下一步位置(tx,ty)
continue;
}
vis[tx][ty] = true;//该点被访问,置为true
path.push_back(i);//放入path中
DFS(tx,ty);//继续DFS (tx,ty)这个点
path.pop_back();//回溯
vis[tx][ty] = false;
}
}
}
bool cmp(vector<int>v1, vector<int>v2) {
for (int i = 0; i < v1.size(); i++) {
if (v1[i] != v2[i]) {
return v1[i] < v2[i];
}
}
}
int main() {
cin >> K;
for (int i = 0; i < K; i++) {
for (int j = 0; j < K; j++) {
cin >> a[i][j];
}
}
DFS(0, 0);
sort(res.begin(), res.end(), cmp);//排序,让字典序最小的在上面
if (res.size() == 0) {//没有路径,输出-1
cout << "-1";
return 0;
}
for (auto i : res) {//输出了所有结果,根据题目要求输出第一个结果就行
for (auto j : i) {
cout << j;
}cout << endl;
}
}
我比赛时是这样做的,案例也跑对了,感觉应该是对的,如果有问题还望读者提出。