题目大概意思:
在一个棋盘中m*n,马从任意位置出发,马是走日的,输入有多组m,n,要求判断是否马可以吧棋盘上每个位置都走到,可以的话打印路径,要求字典序最小,不能就打印impossible.
思路:
深搜+回溯
马是走日的,一共八种组合,要求路径是字典序最小,横坐标是ABCD…纵坐标是12345… 字典序最序最小就得优先y,y从小到大, x就与y对应,也是小的在前
int dx[8] = {-1,1,-2,2,-2,2,-1,1};
int dy[8] = { -2, -2, -1, -1, 1, 1, 2, 2 };
由于是字典序最小,所以必须得从A1开始,
按照图中的顺序:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int maxn = 27;
struct step{
char x, y;
}path[maxn];
int m, n;
int cases;
int visited[maxn][maxn];
bool isSuccess;
void dfs(int i, int j, int num);
//为了让路径字典序最小,ABCD优先,所以是往左走,是优先的
int dx[8] = {-1,1,-2,2,-2,2,-1,1};
int dy[8] = { -2, -2, -1, -1, 1, 1, 2, 2 };
int main()
{
cin >> cases;
for (int i = 1; i <=cases; i++)
{
cin >> m >> n;
memset(visited, 0, sizeof(visited));
isSuccess = false;
visited[1][1] = 1; //起点
dfs(1, 1, 1);
printf("Scenario #%d:\n", i);
if (isSuccess)
{
for (int i = 1; i <= m * n; i++)
printf("%c%c", path[i].y, path[i].x);
printf("\n");
}
else
printf("impossible\n");
if (i != cases)
{
cout << endl;
}
}
}
void dfs(int x, int y, int num)
{
//添加到路径中
path[num].y = y + 'A' - 1;
path[num].x = x + '0';
if (num == m*n){
//已经全部遍历完
isSuccess = true;
return;
}
for (int i = 0; i < 8; i++)
{
//遍历下一个位置
int nx = x + dx[i];
int ny = y + dy[i];
if (0 < nx&&nx <= m && 0 < ny&&ny <= n&&!visited[nx][ny] && !isSuccess)
{
//访问这个点
visited[nx][ny] = 1;
dfs(nx, ny, num + 1);
//撤销
visited[nx][ny] = 0;
}
}
}