这道棋盘题还是挺经典的,问题在于被一个新奇点子卡住好久。

本质上,这道题是一个棋盘中的哈密顿链路问题,这道题一个很经典的优化思路(很多人尝试,都A了),整个棋盘是否存在哈密顿链路,取决于A1是否存在(因为这道题要求的字典序,所以从这里开始找到一定是最优解),但是问题在于,如何将整个图的哈密顿链路存在性与特殊点A1结合是有待商榷的。很多人说的思路很显然是有漏洞的,认为只要有解,必定经过A1,那么可以让A1先到这个点的说法是错误的,这样怎么保证每个点只经过一次呢?此外,将棋盘染色,马的走法决定他的颜色不断变化,有些观点认为,只要一个点可以找到解,那么其他点都可以,这是错误的(可以自己思考),不过如果有解,那也一定是在于A1同色的格子有解

不过代码本质就是为了AC,也许这是对的,只是笔者水平有限,没有想出好的证明。题目也还是使用了朴素方法,每个格子搜一遍,复杂度倒不会太大,此外goto语句纯粹是为了用着方便,不建议

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxs= 11;

struct Node
{
	int x, y;
	Node(int _x= 0, int _y= 0) : x(_x), y(_y) {}
};
int p, q;
stack<Node> sol;
bool ins[maxs][maxs];
int step[8][2]= {{-2, -1}, {-2, 1} ,{-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}};

void PrintAns(const int ok, const int sn)
{
	printf("Scenario #%d:\n", sn);
	if (!ok){
		printf("impossible\n\n");
	}
	else{
		Node cur;
		while (!sol.empty()){
			cur= sol.top();
			sol.pop();
			putchar('A'+cur.x-1);
			printf("%d", cur.y);
		}
		putchar('\n');
		putchar('\n');
	}
}
int DFS(const int x, const int y, const int depth)
{
	if (depth== p*q){
		sol.push(Node(x, y));
		return 1;
	}

	ins[x][y]= 1;
	for (int i= 0; i< 8; ++i){
		int nx= x+ step[i][0], ny= y+step[i][1];
		if (nx> 0 && nx<= q && ny> 0 && ny<= p && !ins[nx][ny]){
			if (DFS(nx, ny, depth+1)){
				sol.push(Node(x, y));
				return 1;
			}
		}
	}
	ins[x][y]= 0;

	return 0;
}

int main(int argc, char const *argv[])
{
	int kase;
	scanf("%d", &kase);

	for (int sn= 1; sn<= kase; ++sn){
		stack<Node> empty;
		swap(sol, empty);

		scanf("%d %d", &p, &q);
		int ok= 0;
		for (int i= 1; i<= q; ++i){
			for (int j= 1; j<= p; ++j){
				memset(ins, 0, sizeof(ins));
				ok= DFS(i, j, 1);
				if (ok){
					goto OK;
				}
			}
		}
	OK: PrintAns(ok, sn);
	}
	return 0;
}