首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

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

2012-12-19 
每天一算法(骑士走棋盘)关于骑士走棋盘问题,,一是不了解走棋盘的规则,二是不了解所要使用的那种由J.C. War

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

关于骑士走棋盘问题,,一是不了解走棋盘的规则,二是不了解所要使用的那种由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;}


热点排行