深度优先搜索经典实例——马踏棋盘算法

深度优先搜索应用比较广泛,最近学习了一下,并结合经典实例——马踏棋盘算法进一步的理解。
马踏棋盘算法是算法设计的经典问题之一;
题目要求简介:国际象棋的棋盘为8*8的方格棋盘,现在将“马”放在任意指定的方格中,按照“马”走棋的规则将“马”进行移动。要求每一个方格只能进入一次,最终使得“马”走遍棋盘64个方格。
其实说到底深度优先搜索和递归思想十分相似;
相关的知识点:
1.回溯法:指导思想比较简单,说白了就是一条路走到黑,碰壁了再回来一条路走到黑······,一般和递归结合使用。
2.哈密尔顿路径:
图G中的哈密尔顿路径是指经过图G中每一个顶点,且只经过一次的一条轨迹,如果这条轨迹是一条闭合的路径,则称为哈密尔顿路径。
下图是国际象棋棋盘以及一匹折腾的马:
在这里插入图片描述
具体代码如下,本人进行了详细的注释,可以放心阅读:

#include<stdio.h>
#include<time.h>

#define X 8
#define Y 8 //定义两个宏,方便以后修改程序数据

int chess[X][Y]//定义一个全局变量,默认初始化为0;
int nextxy(int *x,int *y,int count)//找到基于(x,y)位置的下一个可以走的位置
{
  switch(count)
  {
    case 0:
      if(*x+2<=X-1&&*y-1>=0&&chess[*x+2][*y-1]==0)//对图中的3位置进行判断,前两个条件是判断是否出界,后一个条件是相当于一个标志位,用来判断该位置是否被走过,如果走过则为一;下面七个分支分别对应“马”的其余七种可能走法。
      {
        *x+=2;
        *y-=1;
        return 1;
      }
      break;
    case 1:
      if(*x+2<=X-1&&*y+1<=Y-1&&chess[*x+2][*y+1]==0)
       {
         *x+=2;
         *y+=1;
         return 1;
       }
       break;
    case 2:
      if(*x+1<=X-1&&*y-2>=0&&chess[*x+1][*y-2]==0)
       {
         *x+=1;
         *y-=2;
         return 1;
       }
       break;
    case 3:
      if(*x+1<=X-1&&*y+2<=Y-1&&chess[*x+1][*y+2]==0)
       {
         *x+=1;
         *y+=2;
         return 1;
       }
       break;   
    case 4:
      if(*x-2>=0&&*y-1>=0&&chess[*x-2][*y-1]==0)
       {
         *x-=2;
         *y-=1;
         return 1;
       }
       break;  
    case 5:
      if(*x-2>=0&&*y+1<=Y-1&&chess[*x-2][*y+1]==0)
       {
         *x-=2;
         *y+=1;
         return 1;
       }
       break; 
    case 6:
      if(*x-1>=0&&*y-2>=0&&chess[*x-1][*y-2]==0)
       {
         *x-=1;
         *y-=2;
         return 1;
       }
       break;
    case 7:
      if(*x-1>=0&&*y+2<=Y-1&&chess[*x-1][*y+2]==0)
       {
         *x-=1;
         *y+=2;
         return 1;
       }
       break; 
    defalut:
       break;          
  }
  return 0;    
}
void print()
{
  int i,j;
  for(i=0;i<X;i++)
  {
    for(j=0;j<Y;j++)
    {
      printf("%2d\t",chess[i][j]);
    }
    printf("\n");
  }
  printf("\n");
}

//深度优先遍历棋盘
//(x,y)为位置坐标
//tag是标记位置,每走一步,tag+1;
int Traverchessboard(int x,int y,int tag)
{
  int x1=x,y1=y,flag=0,count=0;
  chess[x][y]=tag;
  if(X*Y==tag)//递归结束条件,当tag 成功到达64时,即所有格子都走完了。
  {
    //打印棋盘
    
    return 1;
  }
  //找到“马”的下一个可走的坐标(x1,y1),如果找到则将flag=1,反之为0;
  flag=nextxy(&x1,&y1,count);
  while(0==flag&&count<7) //这是第一次搜索
  {
    count++;
    flag=nextxy(&x1,&y1,count);
  }
  while(flag)
  {
    if(Traverchessboard(x1,y1,tag+1))//tag+1是累加条件
    {
      return 1;
    }
    //继续找到马的下一步可以走的坐标(x1,y1),如果找到则将flag=1,反之为0;
    x1=x;
    y1=y;
    count++;
    flag=nextxy(&x1,&y1,count);
    while(0==flag&&count<7)//如果上面第一次搜索失败,则进行其余7步搜索;
    {
      count++;
      flag=nextxy(&x1,&y1,count);
    }
  }
  if(0==flag)
  {
    chess[x][y]=0;
  }
  return 0;  
}


int main()
{
  int i,j;
  clock_t start,finish;//头文件time.h定义的宏
  start=clock();//time.h声明的函数;
  for(i=0;i<X;i++)
  {
    for(j=0;j<Y;j++)
    {
      chess[i][j]=0; //初始化
    }
  }
  if(!Traverchessboard(2,0,1))//自行选择参数,这里是从(2,0)开始。//这个地方就比较的迷,看运气吧,我这只要56秒,换个位置可能要几天哦,不信你可以试试嘿。
  {
    printf("falied!\n");
  }
  finish=clock();
  printf("\n本次一共耗时:%f秒\n\n",(double)(finish-start)/CLOCKS_PER_SEC); //CPU的心跳数(finish-start)除以CPU每秒的心跳(CLOCKS_PER_SEC);
  system("pause");
  return 0;
}

程序运行如下图:
在这里插入图片描述

发布了21 篇原创文章 · 获赞 43 · 访问量 3644

猜你喜欢

转载自blog.csdn.net/weixin_44225901/article/details/104462158