跳马问题也称为骑士周游问题,是算法设计中的经典问题。其一般的问题描述是:
考虑国际象棋棋盘上某个位置的一只马,它是否可能只走63步,正好走过除起点外的其他63个位置各一次?如果有一种这样的走法,则称所走的这条路线为一条马的周游路线。试设计一个算法找出这样一条马的周游路线。
此题实际上是一个汉密尔顿通路问题,可以描述为:
在一个8×8的方格棋盘中,按照国际象棋中马的行走规则从棋盘上的某一方格出发,开始在棋盘上周游,如果能不重复地走遍棋盘上的每一个方格,
这样的一条周游路线在数学上被称为国际象棋盘上马的哈密尔顿链。请你设计一个程序,从键盘输入一个起始方格的坐标,由计算机自动寻找并打印
出国际象棋盘上马的哈密尔顿链。
能够想到的思路是用回溯,马在每一个点最多有8种跳法,遍历所有这8种可能的跳法即可得到结果。这是回溯算法中的子集树的类型,与典型的子集树问题类型不同的是,这里每一枝有8种可能的选择,而典型的子集树问题只有0,1两种选择。
下面是该算法的实现:
/**/
/*
* File: KnightTravel1.cpp
* Author: eshow
* Date: 2007-09-10
* Question:
考虑国际象棋棋盘上某个位置的一只马,它是否可能只走63步,正好走过除起点外的其他63个位置各一次?如果有一种这样的走法,则称所走的这条路线为一条马的周游路线。试设计一个算法找出这样一条马的周游路线。
* Solution:
使用回溯法,马每一步至多有8种跳法,遍历这8种跳法,得到结果。这是一个子集树的回溯问题,每一个step[i]都在[0, 7]之间。设棋盘大小为N * N,则时间复杂度为O(8^(N * N)),当N = 8时,算法很慢。
*/
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include
<
stdio.h
>
#include
<
stdlib.h
>
#include
<
memory.h
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
const
int
N
=
8
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
int
step[N
*
N]
=
...
{
-1}
;
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
int
chess[N][N]
=
...
{
0}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
int
Jump[
8
][
2
]
=
...
{
...{
-2, -1}, ...{
-1, -2}, ...{
1, -2}, ...{
2, -1}, ...{
2, 1}, ...{
1, 2}, ...{
-1, 2}, ...{
-2, 1}}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
p
=
0
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
canJump(
int
x,
int
y)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if (x >= 0 && x < N && y >= 0 && y < N && chess[x][y] == 0)
return 1;
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
BackTrace(
int
t,
int
x,
int
y)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if (t >= N * N)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
p++;
for (int i = 1; i <= N * N - 1; ++i)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("%d ", step[i]);
}
printf(" ");
for (int i = 0; i < N; ++i)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int j = 0; j < N; ++j)
printf("%2d ", chess[i][j]);
printf(" ");
}
printf(" ");
exit(1);
//return;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
for (int i = 0; i < 8; ++i)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)