算法思考--------骑士走棋盘(c语言)

《算法思考--------骑士走棋盘(c语言)》
一、
规则说明
             骑士可以从任意一个位置出发,走法和中国象棋的”马”走法类似,”走日”。问:如何走完所有的位置
二、
解法
       
 可以用递归的方法解决,但是纯粹的递归在维度大时没有效率。一个聪明的解法由J.C.Warnsdorft提出:先将最难的位置走完,接下来的路就宽广了
三、
代码实现

#include <stdio.h> 
int travel(int x, int y);
int board[8][8] = {0}; //代表整个棋盘

int main(void) 
{ 
    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 ", board[i][j]); 
		} 
        putchar('\n'); 
	} 
    return 0; 
} 

int travel(int x, int y) 
{ 
    int ktmove1[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; //这两行对应一个点可以走的八个方向的坐标
    int ktmove2[8] = {1, 2, 2, 1, -1, -2, -2, -1}; //
    int nexti[8] = {0}; //这两行存储的是可走的下一步的坐标
    int nextj[8] = {0}; //
    int exists[8] = {0}; //记录每个可走下一步的可走下一步个数
    int i, j, k, m, l; 
    int tmpi, tmpj; 
    int count, min, tmp; 
    i = x; 
    j = y; 
    board[i][j] = 1; //将起点坐标置为1

    for(m = 2; m <= 64; m++)//通过循环来标记2-64
	{
          for(l = 0; l < 8; l++) 
              exists[l] = 0; //这个数组是每次循环都要重复利用的,所以重置0
          l = 0; //这个l也是重复利用的
          for(k = 0; k < 8; k++) //通过循环判断一个坐标的八个方向是否可走
	     { 
                tmpi = i + ktmove1[k]; 
                tmpj = j + ktmove2[k]; 
                if(tmpi < 0 || tmpj < 0 || tmpi > 7 || tmpj > 7) //通过此来筛选是否可走
                     continue;
                if(board[tmpi][tmpj] == 0)//如果可走,就将可走的坐标存储在nexti,nextj中
		  { 
                     nexti[l] = tmpi; 
                     nextj[l] = tmpj; 
                     l++; //把下一步可走位置加一
		  } 
	   } 
         count = l; //将可走位置的数目赋值给count来进行一下判断
         if(count == 0)//没有下一步可走,就返回
	    { 
               return 0; 
	     } 
         else if(count == 1)//只有一个位置可走,就选择这一步,然后继续循环
	   { 
               min = 0; 
	    } 
         else //有多个位置可走时,判断哪一个可走位置的下一步的可走位置最少,就走这一步,意思是把
	   {  //把最困难的走了,这样接下来的空间就大了,可以走完所有位置的可能性就变大了
               for(l = 0; l < count; l++) //同时也说明这种非递归的方法不一定对于所有初始位置都能
		  {            //走遍全图,因为毕竟这种算法使用概率的原理
                      for(k = 0; k < 8; k++) 
			  { 
                              tmpi = nexti[l] + ktmove1[k];
                              tmpj = nextj[l] + ktmove2[k];
                              if(tmpi < 0 || tmpj < 0 || tmpi > 7 || tmpj > 7) 
				  { 
                                      continue; 
				  } 
                              if(board[tmpi][tmpj] == 0)
                                  exists[l]++; //记录可走位置下一步可走位置的个数
			  } 
		  } 
              tmp = exists[0]; 
              min = 0; 
              for(l = 1; l < count; l++) 
	        { 
                  if(exists[l] < tmp) //取得可走位置下一步可走位置最少的那个坐标
	            { 
                        tmp = exists[l]; 
                        min = l; 
		    } 
	        }
	   }
       i = nexti[min]; 
       j = nextj[min]; 
       board[i][j] = m; //将当前步数赋值给那个可走位置下一步可走位置最少的那个坐标
       } 

    return 1; 
} 

四、
效果展示
《算法思考--------骑士走棋盘(c语言)》

    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/zhouzixin053/article/details/22106863
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞