之前,自己写的那个回溯算法,效率非常低,因为他要遍历所有可能的路径,所以解决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;
}