骑士的走法,基本上可以使用递回来解决,但是纯綷的递回在维度大时相当没有效率,一个聪明的解法由J.C. Warnsdorff在1823年提出,简单的说,先将最难的位置走完,接下来的路就宽广了,骑士所要走的下一步, 「为下一步再选择时,所能走的步数最少的一步。使用这个方法,在不使用递回的情况下,可以有较高的机率找出走法(找不到走法的机会也是有的) 。
#include <iostream>
#include<iomanip>//use setw
#include<string.h>//use memset
using namespace std;
int chessBoard[8][8] = { 0 };
bool travel(int, int);
void show();
int main()
{
int startX, startY;
cout << "请输入坐标\n";
cin >> startX >> startY;
if (travel(startX, startY))
show();
else
cout << "fail!\n";
return 0;
}
bool travel(int x, int y)
{
chessBoard[x][y] = 1;
//按照“日”字走法一共有8种
int moveX[8] = { -2, -1, 1, 2, 2, 1, -1, -2 };
int moveY[8] = { 1, 2, 2, 1, -1, -2, -2, -1 };
//按照“日”字走法后的坐标
int nextX[8] = { 0 };
int nextY[8] = { 0 };
//
int tempX, tempY;
int count;//记录下一步能走的总个数
int exist[8] = { 0 };
int min;//记录下一步该走的数组里的下标
for (int m = 2; m <= 64; m++)
{
memset(exist, 0, sizeof(exist));
count = 0;//
for (int i = 0; i < 8; i++)
{
tempX = x + moveX[i];
tempY = y + moveY[i];
if (tempX >= 0 && tempY >= 0 && tempX<=7 && tempY <=7 && chessBoard[tempX][tempY] == 0)
{
nextX[count] = tempX;
nextY[count] = tempY;
count++;
}
}
if (count == 0)
return false;
else if (count == 1)
min = 0;
else
{
for (int i = 0; i < count; i++)
{
for (int j = 0; j < 8; j++)
{
tempX = nextX[i] + moveX[j];
tempY = nextY[i] + moveY[j];
if (tempX >= 0 && tempY >= 0 && tempX<=7 && tempY<=7 && chessBoard[tempX][tempY] == 0)
exist[i]++;
}
}
int temp = 9;
for (int i = 0; i < count; i++)
{
if (exist[i] < temp)
{
temp = exist[i];
min = i;
}
}
}
x = nextX[min];
y = nextY[min];
chessBoard[x][y] = m;
}//for (int m = 2; m <= 64; m++)
return true;
}
void show()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
cout << left << setw(4) << chessBoard[i][j];
cout << ((j == 7) ? "\n" : " ");
}
}
}