OpenJudge NOI 2.5 1490:A Knight‘s Journey
创始人
2024-05-25 07:27:11

【题目链接】

OpenJudge NOI 2.5 1490:A Knight’s Journey
疑问:题目说可以从任意点出发,以任意点结束。为什么我看他人的代码中,只写从(1,1)出发的情况也能过呢?哪位朋友如能理解,希望不吝赐教。

【题目翻译】

一个骑士的旅程

描述

背景:
骑士已经厌倦了一次又一次地看黑白方格,而后决定环游世界。
无论什么时候,一个骑士都会在一个方向移动两格,在与其垂直的方向移动一格。
一个骑士的世界就是它所在的棋盘。我们的骑士生活在一个面积小于8*8的棋盘上,但棋盘仍是个长方形。你能帮助这个有冒险精神的骑士做旅行计划吗?
问题:
找到一条骑士可以对每个格子访问一次的路径。骑士的起点和终点可以是棋盘上的任何格子。

输入:

输入的第一行是一个正整数n。接下来的多行中包含n组测试样例。每个测试样例包含一行两个正整数p和q(1 <= p*q <= 26),代表了一个p*q的棋盘,其中p表示存在多少个不同的方格编号(1,2,…,p),q表示有多少个不同的方格字母,这些字母是拉丁字母表A,B…的前q个字母。

输出:

每种情况的输出以一行"Scenario #i:“起始,其中i是从1开始的情况编号。
然后输出一行,为通过骑士移动访问棋盘上所有方格的路径,只输出字典序排第一的路径字符串。路径字符串应该是单独输出一行的连接了所有访问过的方格名字的字符串。每个方格名字是一个大写字母后面接一个数字。
如果不存在这样的路径,你应该输出一行"impossible”。

样例输入

3
1 1
2 3
4 3

样例输出

Scenario #1:
A1

Scenario #2:
impossible

Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4

来源

TUD Programming Contest 2005, Darmstadt, Germany

【题目考点】

1. 深搜回溯

【解题思路】

国际象棋的棋盘,数字表示行,字母表示列,因而输入p,q指的是该棋盘为p行q列。
要输出的是字典序排第一的路径字符串,因而搜索的起始位置应该按字典序从前向后依次尝试。
起始位置按字典序排列为:A1, A2, …, A8, B1, B2, …,是先看第A列,再看第B列,直到第H列。对于每列,先看第1行,再看第2行。。。

从(x,y)位置出发,可以到达的位置记为(x+a, y+b),其中(a, b)为行与列的偏移量。
根据字典序的要求,先按列从小到大排列,列相同时按行从小到大排列。从(x, y)位置出发可以到达的位置(x+a, y+b)的遍历顺序为(只写出偏移量{a, b})为:{-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1}, {2, 1}, {-1, 2}, {1, 2}。
按照该顺序遍历从(x, y)可以到达的所有位置,进行搜索,搜索从该点出发的所有可能路径。每到达一个新的位置,将该位置保存在路径中(路径用一个vector保存)。搜索结束后,要回溯到前一个位置,继续搜索其他可以到达但未到达的位置。
搜索的过程中做访问格子数量的计数,如果访问数量达到了p*q,则骑士完成了遍历棋盘上的每个格子,输出路径。

【题解代码】

解法1:深搜回溯

#include
using namespace std;
#define N 30
struct Pair
{int x, y;//x:行 y:列 Pair(){}Pair(int a, int b):x(a), y(b){}
};
vector path;//保存路径 每个元素
int dir[8][2] = {{-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1}, {2, 1}, {-1, 2}, {1, 2}};
bool vis[N][N], hasAns;//vis[i][j]:(i,j)是否访问过  hasAns:是否已经找到答案 
int p, q;//地图p行q列 
void dfs(int sx, int sy)
{for(int i = 0; i < 8; ++i){int x = sx+dir[i][0], y = sy+dir[i][1];if(x >= 1 && x <= p && y >= 1 && y <= q && vis[x][y] == false){vis[x][y] = true;path.push_back(Pair(x, y));if(path.size() == p*q)//如果路径中已经保存了地图中的所有位置,即已经访问了所有位置,则找到路径 {hasAns = true;return;}dfs(x, y);if(hasAns)return;vis[x][y] = false;path.pop_back();}}
}
int main()
{int n;cin >> n;for(int k = 1; k <= n; ++k)//k:情况编号 {cin >> p >> q;memset(vis, 0, sizeof(vis));path.clear();hasAns = false; for(int j = 1; j <= q; ++j)//先遍历列,再遍历行 {for(int i = 1; i <= p; ++i){if(vis[i][j] == false){vis[i][j] = true;path.push_back(Pair(i, j));if(path.size() == p*q)hasAns = true;dfs(i, j);if(hasAns)break;vis[i][j] = false;path.pop_back();}}if(hasAns)break;}cout << "Scenario #" << k << ":" << endl;if(hasAns){for(Pair pr : path)cout << char(pr.y-1+'A') << pr.x;}elsecout << "impossible";cout << endl << endl;}return 0;
}

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...