题目:
有一m*n的棋盘,把马放在任意位置,马按照中国象棋法起跳,求能返回原位置的所有路线。
用回溯法求解此题(其实也就是最基本的深搜):
从起点开始,向可以扩展的位置扩展(由题意可知,一共有八种扩展方法);
到了新的位置,先判断是不是到达原位置,如果是,则输出该路线,并会退到上一个位置,继续下一个位置的扩展;
如果不是,再判断是否超出棋盘,或者产生回路,如果是,则回退到上一个位置;
如果以上都不成立,那么就从这一新位置继续向下扩展;
每当一个位置的八种情况都扩展完了,就回退到上一位置;
以上为此题的思路。
也就是一个回溯思想的应用,DFS在我看来,就是对回溯的应用(如果过于绝对,请指正)。
代码可以用递归,也可以非递归。。一直都是写的递归,这次尝试了一下非递归,果然各种错啊。。。。
最让人郁闷的是二维数组的赋初值竟然弄错了。。。这个问题一直没发现,让我找错找了好久。。。
代码:
#include<iostream>
using namespace std;
#define maxn 5
int choose[8][2]={{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}};
struct node{
int x;
int y;
int p;
};
int flag[10][10];
bool istrue(int x1,int y1){
if(flag[x1][y1])
return false;
if(x1<=0||x1>4||y1<=0||y1>3)
return false;
return true;
}
int main(){
int start,end;
while(cin>>start>>end){
node a[100];
node b[100][100];
memset(flag,0,sizeof(flag));
int times=0;
int time=0;
node temp;
temp.x=start;
temp.y=end;
temp.p=0;
a[times++]=temp;
flag[start][end]=1;
while(times>0){
node temp1=a[times-1];
node temp2;
int i;
for(i=temp1.p;i<8;i++){
temp2.x=temp1.x+choose[i][0];
temp2.y=temp1.y+choose[i][1];
temp2.p=0;
if(temp2.x==start&&temp2.y==end){
for(int j=0;j<times;j++){
b[time][j]=a[j];
}
time++;
continue;
}
if(istrue(temp2.x,temp2.y)){
a[times-1].p=i+1;
a[times++]=temp2;
flag[temp2.x][temp2.y]=1;
break;
}
}
if(i>=8){
times--;
flag[a[times].x][a[times].y]=0;
}
}
for(int k=0;k<time;k++){
int temp3=b[k][0].x;
int temp4=b[k][0].y;
int temp5=0;
while(temp3!=0||temp4!=0){
cout<<temp3<<" "<<temp4<<endl;
temp5++;
temp3=b[k][temp5].x;
temp4=b[k][temp5].y;
}
cout<<endl;
}
}
return 0;
}