最近上了算法課,寫了一個判斷M*N的馬跳圖中,是否存在漢密頓迴路。用的是完全遍歷的方法,這裏沒有使用遞歸的方法,一直遍歷圖中的路徑節點,直到找到一條滿足條件漢密頓迴路則停止,當然,這樣的算法效率比較低,特別是圖中沒有漢密頓迴路時,要遍歷所有可能的路徑。
希望與大家共同學習,共同進步
後續會寫一個用分支限界來判定的方法。。。敬請期待!
#include<stdio.h>
#define M 6 //行數
#define N 6 //列數
int islegal(int x, int y);
void main(void)
{
int flag[M][N]; //標註是否走過
int route[M*N][8]; //標註每個方向的路徑是否可走,0爲不可走,1爲可走
//標記每一步的前一步的行和列
int fromcol[M*N]={0};
int fromrow[M*N]={0};
int direct[][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2}}; //每步可以走的八個方向
int curcol=-1; //當前行
int currow=-1; //當前列
int nextcol=-1; //下一行
int nextrow=-1; //下一列
// 初始化flag
int i,j;
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
flag[i][j]=0;
}
}
//初始化route
int k;
int pos; //當前在數組中的位置
for(curcol=0; curcol<M; curcol++)
{
for(currow=0; currow<N; currow++)
{
pos=curcol*N+currow;
for(k=0; k<8; k++)
{
nextcol=curcol+direct[k][0];
nextrow=currow+direct[k][1];
if(islegal(nextcol,nextrow))
{
route[pos][k]=1;
}
else
{
route[pos][k]=0;
}
}
}
}
//回溯遍歷尋找路徑
curcol=0;
currow=0;
pos=0;
int num=1;
while(num<=M*N) //當又回到原點時結束
{
for(i=0;i<8;i++) //尋找下一個合適的步
{
nextcol=curcol+direct[i][0];
nextrow=currow+direct[i][1];
if(nextcol==0 && nextrow==0 && num==M*N)
{
num++; //爲了退出循環
break;
}
if(islegal(nextcol,nextrow) && flag[nextcol][nextrow]==0)
{
if(route[pos][i])
{
flag[curcol][currow]=1;
route[pos][i]=0; //防止回溯時走已走過的路
curcol=nextcol;
currow=nextrow;
pos=curcol*N+currow;
fromcol[pos]=curcol-direct[i][0]; //保存前一個點的位置
fromrow[pos]=currow-direct[i][1];
num++;
break;
}
}
}
if(i==8) //沒有找到合適的步,進行回溯
{
if(flag[curcol][currow]==1)
{
flag[curcol][currow]=0;
}
pos=curcol*N+currow;
for(j=0; j<8; j++) //恢復退出的節點
{
if(islegal(curcol+direct[j][0],currow+direct[j][1]) && route[pos][j]==0)
{
route[pos][j]=1;
}
}
curcol=fromcol[pos];
currow=fromrow[pos];
pos=curcol*N+currow;
num--;
if(num==0)break;
}
}
printf("%d\n",num);
printf("%d,%d",curcol,currow);
if(num==0)
{
printf("無 漢密頓迴路\n");
}
else if(num==M*N+1)
{
printf("有 漢密頓迴路\n");
}
}
// 所在位置合法是返回值爲1;否則返回0
int islegal(int x, int y)
{
if((x>=0 && x<M) && (y>=0 && y<N))return 1;
else
{
return 0;
}
}