ZOJ 1091 TKP(traveling knight problem) 的一些心得

ZOJ 1091 TKP(traveling knight problem) 一些心得

写这个贴子的最主要原因是怕自己以后忘记深搜和广搜这两兄弟的思路了,同时也希望读者能有所收获😝

zoj 1091原题

A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight moves between two given squares and that, once you have accomplished this, finding the tour would be easy.
Of course you know that it is vice versa. So you offer him to write a program that solves the “difficult” part.

Your job is to write a program that takes two squares a and b as input and then determines the number of knight moves on a shortest route from a to b.

Input Specification
The input file will contain one or more test cases. Each test case consists of one line containing two squares separated by one space. A square is a string consisting of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard.
Output Specification
For each test case, print one line saying “To get from xx to yy takes n knight moves.”.
Sample Input
e2 e4
a1 b2
b2 c3
a1 h8
a1 h7
h8 a1
b1 c3
f6 f6
Sample Output
To get from e2 to e4 takes 2 knight moves.
To get from a1 to b2 takes 4 knight moves.
To get from b2 to c3 takes 2 knight moves.
To get from a1 to h8 takes 6 knight moves.
To get from a1 to h7 takes 5 knight moves.
To get from h8 to a1 takes 6 knight moves.
To get from b1 to c3 takes 1 knight moves.
To get from f6 to f6 takes 0 knight moves.

题目大意

输入棋盘上两个点的位置,计算出从起始点到终点的最短距离。
(其中,用a-h代表点所在棋盘上的列,用1-8代表点所在棋盘上的行)

思路

1、国际象棋中knight的行走规则是走对角线,如图所示(我也不造为啥图片会这么大😥):
在这里插入图片描述
2、对于要找到某个目标的问题,通常所采用的都是搜索算法,这里我采用了“无头苍蝇”搜索法(嘻嘻,我自己瞎起的,其实别人叫“无信息图搜索”):
深度优先算法广度优先算法

深度优先算法(DFS)

   ## 思路:
       定义一个规则集,用于作用于当前所访问的点,使之生成后续的点。这个
   规则集是由8个元素组成的,对应于向8个不同的方向移动时,当前点将会发生
   的坐标上的变化。
       比如当前点是(3,4),那么其**一步**到点(2,6)所被作用的规则就
       是(-1,2)
       规则集为:
       int rules[8][2] = { {-1,2},{-2,1},{-2,-1},{-1,-2},{1,2},
       {2,1},{2,-1},{1,-2} };//从左上到左下,再从右上到右下

步骤:
1、访问当前所到的点,如果当前点是终点,进行回溯(回溯的意思就是:
行啦,后面的点我不走啦,回家去)。
2、如果当前点不合法,进行回溯(不合法就是在棋盘上这个点是不存在
的)。
3、如果当前点已经被走过,进行回溯(某个点如果已经被走过,再次走这
个点的话深搜还是会按照原来的轨迹走,造成死循环)。
4、当前搜索深度超过预先设定的深度,进行回溯(深度优先还需设置一
个深度限制,不然若某些问题如果没有解,深搜会无限递归下去)
5、运用规则集作用于当前点,生成下一步可能会走的点。
6、对生成的点利用步骤1-6进行访问。(这里就是递归啦)

       下面是代码:
    void DFS(point start, point end, int num) {
   
	//到达终点
	if (start == end) {
   
		if (num < step) {
   
			step = num;
		}
		return ;
	}
	//如果 start 和 end 其中之一不合法,则返回
	if (!isLegal(start) || !isLegal(end)) return;
	//该点已被访问过
	if (visit[start.x][start.y] == 1) return;
	//超出搜索深度
	if (num > 10) return;
	//访问此点
	visit[start.x][start.y] = 1;//标记此点已被走过,初始值为0
	for (int n = 0; n < 8; n++) {
   
		point newStart;
		newStart.x = start.x + rules[n][0];
		newStart.y = start.y + rules[n][1];	
		DFS
  • 10
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值