您的位置:首页 > 其它

每天一算法(骑士走棋盘)

2012-12-11 15:58 288 查看
关于骑士走棋盘问题,,一是不了解走棋盘的规则,二是不了解所要使用的那种由J.C. Warnsdorff在1823年提出的解法的意思是什么。。所以只能读代码,,但还真读懂了人家的代码,并自己实现了一下。。

说明

骑士旅游(Knight tour)在十八世纪初倍受数学家与拼图迷的注意,它什么时候被提出已不可考,骑士的走法为西洋棋的走法,骑士可以由任一个位置出发,它要如何走完[所有的位置?

解法

骑士的走法,基本上可以使用递回来解决,但是纯綷的递回在维度大时相当没有效率,一个聪明的解法由J.C. Warnsdorff在1823年提出,简单的说,先将最难的位置走完,接下来的路就宽广了,骑士所要走的下一步,「为下一步再选择时,所能走的步数最少的一步。」,使用这个方法,在不使用递回的情况下,可以有较高的机率找出走法(找不到走法的机会也是有的)。

自己实现的代码如下:

int ChessBoard[8][8] = {0};

bool Travel(int FirstX,int FirstY)
{
int movex[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int movey[8] = {1, 2, 2, 1, -1, -2, -2, -1};

ChessBoard[FirstX][FirstY] = 1;
int NextX = FirstX;
int NextY = FirstY;
int NextStepX[8] = {0};
int NextStepY[8] = {0};
int ExitS[8] = {0};

for (int m = 2;m<65;m++)
{
for (int i = 0;i<8;i++)
ExitS[i] = 0;
int Count = 0;
for (int i = 0;i<8;i++)
{
int TemI = NextX + movex[i];
int TemJ = NextY + movey[i];
if (TemI<0||TemI>7||TemJ<0||TemJ>7)
{
continue;
}
if (0 == ChessBoard[TemI][TemJ])
{
NextStepX[Count] = TemI;
NextStepY[Count] = TemJ;
Count++;

}
}
//到这里,Cout表示当前点有几种走法。NextStep中存储各种走法的坐标。

int min = 0;
if (Count<1)
{
return false;
}
if (1 == Count)
{
min = 0;
}
else
{//这一步是为了找到下一次走法中最少种走法的那一步
for (int i = 0;i<Count;i++)
{
for (int j = 0;j<8;j++)
{
int TemI = NextStepX[i]+movex[j];
int TemJ = NextStepY[i]+movey[j];
if (TemI<0||TemI>7||TemJ<0||TemJ>7)
{
continue;
}
if (0 == ChessBoard[TemI][TemJ])
{
ExitS[i]++;
}
}
}
int tem = ExitS[0];
min = 0;
for (int i = 1;i<Count;i++)
{
if (tem > ExitS[i])
{
tem = ExitS[i];
min = i;
}
}
}

NextX = NextStepX[min];
NextY = NextStepY[min];
ChessBoard[NextX][NextY] = m;

}
return true;
}

int main()
{
int startx, starty;
int i, j;
printf("输入起始点:");
scanf("%d %d", &startx, &starty);
if(Travel(startx, starty)) {
printf("游历完成!\n");
}
else {
printf("游历失败!\n");
}
for(i = 0; i < 8; i++) {
for(j = 0; j < 8; j++) {
printf("%2d ", ChessBoard[i][j]);
}
putchar('\n');
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐