POJ2488 A Knight's Journey

题目:http://poj.org/problem?id=2488

题目大意:可以从任意点开始,只要能走完棋盘所有点,并要求字典序最小,不可能的话就impossible;

思路:dfs+回溯,因为字典序最小,如果可以的话,肯定是从(1,1)开始的。然后递归搜索该点的所有方向,不能满足就回溯,直到找到能满足的,或者一直找不到。

代码+注释:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;

bool vis[27][27];
int des[8][2] = {-2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1};//八个方向 

int T, n, m, tempx, tempy;

struct node{
	int x;
	int y;
}stu[27];

bool flag;
bool judge(int x, int y) {
	if(x < 1 || x > n || y < 1 || y > m)
		return false;
	if(vis[x][y])
		return false;
	if(flag)
		return false;
	return true;
}

void dfs(int x, int y, int num) {
		stu[num].x = x;
		stu[num].y = y;
		if(num == m * n) {//跑完所有的点了 
			flag = true; 
			return;//这里的return 不是直接出去,而是返回上一状态?我的理解 
		}
		for(int i =0; i < 8; i++) {//遍历所有的方向 
			tempx = x + des[i][0];
			tempy = y + des[i][1];
			if(judge(tempx, tempy)) {//这个点满足条件 
				vis[tempx][tempy] = true;//标记访问过 
				dfs(tempx, tempy, num + 1);//继续搜索,点数+1 
				vis[tempx][tempy] = false;//说明该点虽然满足条件,但是无法走完全部的点,因此回溯 
			}
		}
}

int main() {
	scanf("%d", &T);
	int j = 1;
	while(T--) {
		scanf("%d%d", &m, &n);
		flag = false;
		memset(vis, false, sizeof(vis));
		vis[1][1] = true;//肯定是从第一个开始的(保证字典序最小) 
		dfs(1, 1, 1);// (1,1,第一个点) 
		printf("Scenario #%d:
", j++);
		if(flag) {
			for(int i = 1; i <= n * m; i++) {
				printf("%c%c", 'A' + stu[i].x - 1, '1' + stu[i].y - 1);
			}
			cout << endl;
		} else cout << "impossible" << endl; 
		cout << endl;
	}
}
原文地址:https://www.cnblogs.com/ACMerszl/p/9572945.html