关于马跳图的汉密顿回路问题


之前,自己写的那个回溯算法,效率非常低,因为他要遍历所有可能的路径,所以解决10以上的问题就会显得力不从心,甚至永远无法解出

下面是一个师姐写的算法,效率非常高,用到了贪心算法。避免了无止境的回溯,提高了效率。


#include  <iostream.h>  
#include  <iomanip.h>  
#include <time.h>
#define  ROW  6  
#define  LINE ROW       
#define  NUM  ROW*LINE         
int  board[ROW][LINE];
//两个数组存储对应的偏移量  
int  stepRow[8] ={-1,-2,-2,-1,1,2,2,1};  
int  stepLine[8]={-2,-1,1,2,2,1,-1,-2};  
//求  (i,j)  的出口数,各个出口对应的号存在 a[]  中。
int  exitn(int i,int j,int a[])
{  
	int  i1,j1,k,count;  
	for(count= k=0;k <8;k++){  
		i1=i+stepRow[k];  
		j1=j+stepLine[k];  
		if(i1>=0&&i1<ROW&&j1>=0&&j1<LINE&&board[i1][j1]==0){  
			a[count++]=k;  
		}  
	}  
	return  count;  
} 

 
//判断选择下个出口,s  是顺序选择法的开始序号  
int  next(int i ,int j){  
	int m,kk,a[8],b[8],temp;  
	m = exitn(i,j,a);  
	if(m==0)    
		return  -1;      //没有出口的情况 
	
	for(int min=9,k=0;k<m;k++){ //逐个考虑取下一步最少的出口的出口  
		temp=exitn(i+stepRow[a[k]],j+stepLine[a[k]],b);  
		if(temp<min){  
			min=temp;  
			kk =a[k];  
		}  
	}  
	return  kk;  
}  

int  main()  
{  
   int i,j,step,no,flag=0;  
        //对每个位置的点都进行计算得到各个点的结果 

   unsigned beg,end;
   beg=(unsigned)time(NULL);


   for(int sx=0;sx<ROW;sx++)  
	   for(int sy=0;sy<LINE;sy++)
	   {  
		  //start= 0;  
		  do{  
			  for(i=0;i<ROW;i++)  
				  for(j=0;j<LINE;j++)  
				      board[i][j]= 0;  
              board[sx][sy]= 1;  
              i=sx;j=sy;  
              for(step=2;step<=NUM;step++)
			  {  
				  if((no=next(i,j))== -1)  
                      break;  
                  i+=stepRow[no];  
                  j+=stepLine[no];  
                  board[i][j]=step;  
			  }  
			  if(step >NUM||no==-1)  
				  break;  
		  }while(step<=NUM); 
		  

		  int  stepRow[8] ={-1,-2,-2,-1,1,2,2,1};  
		  int  stepLine[8]={-2,-1,1,2,2,1,-1,-2};
		  //if(no!=-1&&((sx+2==i||sx-2==i)&&(sy+1==j||sy-1==j))||((sx+1==i||sx-1==i)&&(sy+2==j||sy-2==j)))
		  if(no!=-1&&( (sx-1==i&&sy-2==j)||(sx-2==i&&sy-1==j)||(sx-2==i&&sy+1==j)
			  ||(sx-1==i&&sy+2==j)||(sx+1==i&&sy+2==j)||(sx+2==i&&sy+1==j)||(sx+2==i&&sy-1==j)
			  ||(sx+1==i&&sy-2==j) ))

		  {  
			  cout<<"ok"<<endl;
			  for(i=0;i<ROW;i++)
			  {  
				  for(j=0;j<LINE;j++)  
					  cout<<setw(5)<<board[i][j];  //打印  
				  // cout<<board[i][j]<<'/t';
				  cout<<endl; 
				  
			  }
			  flag=1;
		  }
		  
		  if(flag)  break;
	   }
	   if(!flag)
	   {
		   cout<<"no circle"<<endl;
	   }

	   end=(unsigned)time(NULL);
	   cout<<endl<<"need"<<setw(3)<<end-beg<<" second"<<endl;
	   //cout<<endl<<"no circle"<<endl;
	   return  0;  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值