书里面的例题,这里记录一下代码。
如下图所示,给出一个N*M的迷宫图和一个入口、一个出口。编序打印一条从迷宫入口到出口的路径。这里黑色方块的单元表示走不通(用-1表示),白色方块的单元表示可以走(用0表示)。只能往上、下、左、右四个方向走。如果无路则输出“no way.”。
【算法分析】
只要输出一条路径即可,所以是一个经典的回溯算法问题,下面分别是回溯(深搜)程序和广搜程序。
深搜代码:
1 #include <stdio.h> 2 3 #define maxN 1003 4 #define maxM 1003 5 6 int n,m,desX,desY,souX,souY,totalStep,a[maxN*maxM],b[maxN*maxM],map[maxN][maxM]; 7 bool f; 8 9 int move(int x, int y,int step) 10 { 11 map[x][y]=step; //走一步,作标记,把步数记下来 12 a[step]=x; b[step]=y; //记路径 13 if((x==desX)&&(y==desY)) 14 { 15 f=1; 16 totalStep=step; 17 } 18 else 19 { 20 if( (y!=m)&&(map[x][y+1]==0) ) move(x,y+1,step+1); //向右 21 if( (!f)&&(x!=n)&&(map[x+1][y]==0) ) move(x+1,y,step+1); //往下 22 if( (!f)&&(y!=1)&&(map[x][y-1]==0) ) move(x,y-1,step+1); //往左 23 if( (!f)&&(x!=1)&&(map[x-1][y]==0) ) move(x-1,y,step+1); //往上 24 } 25 } 26 27 int main(int argc, char *argv[]) 28 { 29 int i,j; 30 freopen("migong2.in","r",stdin); 31 //freopen("migong.out","w",stdout); 32 scanf("%d%d",&n,&m); //n行m列的迷宫 33 for (i=1;i<=n;i++) //读入迷宫,0表示通,-1表示不通 34 for (j=1;j<=m;j++) 35 scanf("%d",&map[i][j]); 36 scanf("%d%d%d%d",&souX,&souY,&desX,&desY);//出发点和目的地点 37 f=0;//f=0表示无解;f=1表示找到了一个解 38 39 move(souX,souY,1); 40 41 if(f) 42 { 43 for (i=1;i<=totalStep;i++) //输出走迷宫的路径 44 printf("%d,%d ",a[i],b[i]); 45 } 46 else printf("no way. "); 47 /**/ 48 return 0; 49 }
上述代码搜索结果:
广搜代码1:
1 #include<iostream> 2 using namespace std; 3 int u[5]={0,0,1,0,-1},//右,下,左,上 4 w[5]={0,1,0,-1,0}; 5 int n,m,i,j,desx,desy,soux,souy,head,tail,x,y,a[51],b[51],pre[51],map[51][51]; 6 bool f; 7 int print(int d) 8 { 9 if (pre[d]!=0) print (pre[d]); //递归输出路径 10 cout<<a[d]<<","<<b[d]<<endl; 11 } 12 int main() 13 { 14 int i,j; 15 freopen("mgong.in","r",stdin); 16 freopen("mgong.out","w",stdout); 17 cin>>n>>m; //n行m列的迷宫 18 for (i=1;i<=n;i++) //读入迷宫,0表示通,-1表示不通 19 for (j=1;j<=m;j++) 20 cin>>map[i][j]; 21 cin>>soux>>souy; //入口 22 cin>>desx>>desy; //出口 23 head=0; 24 tail=1; 25 f=0; 26 map[soux][souy]=-1; 27 a[tail]=soux; b[tail]=souy; pre[tail]=0; 28 while (head!=tail) //队列不为空 29 { 30 head++; 31 for(i=1;i<=4;i++) //4个方向 32 { 33 x=a[head]+u[i]; y=b[head]+w[i]; 34 if((x>0)&&(x<=n)&&(y>0)&&(y<=m)&&(map[x][y]==0)) 35 { //本方向上可以走 36 tail++; 37 a[tail]=x; b[tail]=y; pre[tail]=head; 38 map[x][y]=-1; 39 if ((x==desx)&&(y==desy)) //扩展出的结点为目标结点 40 { 41 f=1; 42 print(tail); 43 break; 44 } 45 } 46 } 47 if(f) break; 48 } 49 if(!f) cout<<"no way."<<endl; 50 return 0; 51 }
广搜代码2:
1 #include<iostream> 2 #include<stdio.h> 3 #include<queue> 4 using namespace std; 5 6 struct obj 7 { 8 int x,y,index;//index表示坐标(x,y)在pre[]中的坐标 9 }; 10 11 int u[5]={0,0,1,0,-1},//右,下,左,上 12 w[5]={0,1,0,-1,0}; 13 int n,m,map[51][51],desx,desy,soux,souy,a[51],b[51],pre[51],step; 14 queue<obj> q; 15 bool f; 16 17 int print(int d) 18 { 19 if (pre[d]!=-1) print (pre[d]); //递归输出路径 20 printf("%d,%d ",a[d],b[d]); 21 } 22 23 int main(int argc, char *argv[]) 24 { 25 int i,j,x,y; 26 struct obj temp,temp2; 27 freopen("mgong.in","r",stdin); 28 freopen("mgong.out","w",stdout); 29 cin>>n>>m; //n行m列的迷宫 30 for (i=1;i<=n;i++) //读入迷宫,0表示通,-1表示不通 31 for (j=1;j<=m;j++) 32 cin>>map[i][j]; 33 cin>>soux>>souy; //入口 34 cin>>desx>>desy; //出口 35 f=0;//f=0表示无解;f=1表示找到了一个解 36 37 map[soux][souy]=-1; 38 step=0; 39 a[step]=soux; 40 b[step]=souy; 41 pre[step]=-1;//pre[step]=k表示(a[step],b[step])的前驱节点是(a[k],b[k]) 42 temp.x=soux; 43 temp.y=souy; 44 temp.index=step;//index表示坐标(x,y)在pre[]中的坐标 45 q.push(temp); 46 47 while(!q.empty()) 48 { 49 temp=q.front(); q.pop(); 50 for(i=1;i<=4;i++) //4个方向 51 { 52 x=temp.x+u[i]; y=temp.y+w[i]; 53 if((x>0)&&(x<=n)&&(y>0)&&(y<=m)&&(map[x][y]==0)) 54 { //本方向尚可以走 55 step++; 56 a[step]=x; b[step]=y; pre[step]=temp.index; 57 temp2.x=x; 58 temp2.y=y; 59 temp2.index=step; 60 q.push(temp2); 61 map[x][y]=-1; 62 63 if((x==desx)&&(y==desy)) //扩展出的结点为目标结点 64 { 65 f=1; 66 print(step); 67 break; 68 } 69 } 70 } 71 if(f) break; 72 } 73 if(!f) cout<<"no way."<<endl; 74 return 0; 75 }
上述广搜代码的搜索结果: