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