http://poj.org/problem?id=2488
题目大意:骑士厌倦了一遍又一遍地看到同样的黑白方块,于是决定去旅行。
世界各地。当一个骑士移动时,他走的是“日”字。骑士的世界是他赖以生存的棋盘。我们的骑士生活在一个棋盘上,它的面积比普通的8 * 8板要小,但它仍然是矩形的。你能帮这个冒险的骑士制定旅行计划吗? 找到一条路,这样骑士每一次都能到每一个广场。骑士可以在棋盘的任何方格上开始和结束。输入从第一行的正整数n开始。下面的行包含n个测试用例。每个测试用例由一个带有两个正整数p和q的单行组成,其中1 <= p * q <= 26。这表示一个p * q棋盘,其中p描述了多少个不同的数1,…p存在,q描述存在多少个不同的字母。这些是拉丁字母表中的第一个q字母:A,…每个场景的输出从包含“Scenario #i:”的一行开始,其中i是从1开始的场景的数量。然后打印一行一行,其中包含了字母顺序的第一路径,它访问棋盘上的所有方块,然后是空行。通过将访问的方块的名称连接起来,可以在一行中给出路径。每个方名称由大写字母和数字组成。
如果不存在这样的路径,那么您应该在一行上输出impossible的内容。
也就是说横坐标时是字母(向右为正),纵坐标是数字(向下为正),骑士需要走完全图的方格,并找出包含了字母顺序的第一条路径,那么这就暗示了骑士的起点坐标一定是A1,只有是按字母排序第一个一定是A1。骑士走的是“日”字,那么根据字母排序骑士的横坐标和纵坐标减少或增加的遍历顺序是8个方向(-2,-1)(-2,1)(-1,-2)(-1,2)(1,-2)(1,2)(2,-1)(2,1),这样的遍历顺序,得到的第一条路径一定是按字母顺序的路径。
算法思想:回溯法,问题的解空间树是一颗八叉树,分别对应八个方向,设置相应的剪枝函数,1)如果出界,舍弃相应子树;2)如果找到了一条路径(一定是按字母排序的路径),用一个isSoluted记录,如果问题解决,则减去相应子树;3)我们可以用visited[ ][ ]记录该方格被访问,减去相应子树(重复走回路),并在回溯时设为未访问。
1 #include <cstring>//使用memset() 2 #include <iostream> 3 using namespace std; 4 //按字典排序的行走方向 8叉树 5 const int dx[8] = { -2, -2, -1, -1, 1, 1, 2, 2 }; 6 const int dy[8] = { -1, 1, -2, 2, -2, 2, -1, 1 }; 7 const int N = 27; 8 bool visited[N][N];//判断方格是否被访问 9 struct step { //走路的记录 10 char x, y; 11 }; 12 step path[N];//记录路径的 13 bool isSoluted;//能否走通 14 int cases, p, q;//记录案例数,p行123... q列ABC... 15 void Backtrade(int x, int y, int t)//x 和 y 为当前坐标 t为深度 16 { 17 path[t].x = x + 'A' - 1; //转为 char 记录走的路径 18 path[t].y = y + '0'; 19 if (t == p * q)//如果有一条路走完全部 则可解 直接退出回溯 20 { 21 isSoluted = true; 22 return; 23 } 24 for (int i = 0; i < 8; i++) 25 { 26 int nx = x + dx[i]; 27 int ny = y + dy[i]; 28 //剪枝函数 出界 或 已访问过 或 问题已解决 不进入相应子树 29 if (0 < nx && nx <= q && 0 < ny && ny <= p&& !visited[nx][ny] && !isSoluted) 30 { 31 visited[nx][ny] = true; 32 Backtrade(nx, ny, t + 1); 33 visited[nx][ny] = false;//回溯时撤回标记 34 } 35 } 36 } 37 int main() 38 { 39 cin>>cases; 40 for (int c = 1; c <= cases; c++) 41 { 42 isSoluted = false; 43 cin >> p >> q; 44 memset(visited, false, sizeof(visited)); 45 visited[1][1] = true; //从第一个字典序起点开始走 46 Backtrade(1, 1, 1); 47 cout<<"Scenario #"<<c<<":"<<endl; 48 if (isSoluted) 49 { 50 for (int i = 1; i <= p * q; i++) 51 cout << path[i].x << path[i].y; 52 cout << endl; 53 } 54 else 55 cout<<"impossible"<<endl; 56 cout << endl; 57 } 58 return 0; 59 }
转载于:https://www.cnblogs.com/DA799422035/p/8994075.html
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/101680.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...