题意:在给定的p*q的棋盘上,问一个骑士是否能够以一个特定的走法从棋盘上的某个位置出发,然后不重复的遍历整个棋盘上的位置。最后的结果要按字典序最小的方式输出。(列用字母表示,行用数字表示,且最后输出是字母在前)。
想法:dfs没什么说的。。但是我却依然不会。。衰。。脑子有点晕。。我写的dfs没用递归,直接写的。。贴代码。。
代码如下:
#pragma warning(disable:4996)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cstring>
#include<sstream>
#include<set>
#include<string>
#include<iterator>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
//每个位置可能的行走方式
struct item {
int a;
int b;
}mov[8] = { { -2,-1 },{ -2,1 },{ -1,-2 },{ -1,2 },{ 1,-2 },{ 1,2 },{ 2,-1 },{ 2,1 } };
//每个位置的坐标,以及经历了多少种行走方式
struct Elem {
int x;
int y;
int dir;//对应上面的mov数组
};
//记录是否经过某个位置
bool mark[100][100];
int main(void) {
int time = 0, n, p, q;
cin >> n;
while (n--) {
memset(mark, 0, sizeof(mark));
cin >> p >> q;
stack<Elem> ss;//用栈代替递归的功能,将前一个位置的坐标以及最后一次的行走方式压入栈中
item way[100];//记录路径
way[1].a = 1, way[1].b = 1;//路径的第一步总是A1
int signal = 1, flag = 1;//signal记录路径的长度,flag记录是否找到完整的长度为p*q路径
int x, y, d;//当前的坐标值,与行走方式
Elem now = { 1,1,0 };
ss.push(now);
mark[1][1] = 1;
while (!ss.empty() && flag) {
now = ss.top();
ss.pop();
x = now.x, y = now.y, d = now.dir;
while (d < 8 && flag) {
int m = x + mov[d].a, n = y + mov[d].b;//使用d的行走方式之后到达的(m,n)点
if (signal == p*q)flag = 0;//判断是否已经遍历所有点
if (m<=0 || m>q||n<=0 || n>p)++d;//判断(m,n)是否可达
else if (!mark[m][n]) {//判断(m,n)是否之前已经到达
mark[m][n] = 1;
way[++signal].a = m, way[signal].b = n;
now.x = x, now.y = y, now.dir=d+1;//更新前一个点的数据
ss.push(now);
x = m, y = n, d = 0;//更新为当前点
}
else ++d;
}
//如果已经遍历完所有行走方式都不可以,则压入栈中最后一个元素的位置清零,路径减一
mark[way[signal].a][way[signal].b] = 0;
signal--;
}
time++;
cout << "Scenario #" << time << ":" << endl;
if (flag)
cout << "impossible" << endl;
else {
for (int i = 1; i <= p*q; ++i)
cout <<(char)( 'A' + way[i].a - 1) << way[i].b;
cout << endl;
}
cout << endl;
}
return 0;
}