深度優先搜索經典實例——馬踏棋盤算法

深度優先搜索應用比較廣泛,最近學習了一下,並結合經典實例——馬踏棋盤算法進一步的理解。
馬踏棋盤算法是算法設計的經典問題之一;
題目要求簡介:國際象棋的棋盤爲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;
}

程序運行如下圖:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章