迷宫问题

书里面的例题,这里记录一下代码。

如下图所示,给出一个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\n",a[i],b[i]);
45     }
46     else  printf("no way.\n");
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\n",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 }

上述广搜代码的搜索结果:

 

posted on 2017-07-24 11:38  华山青竹  阅读(746)  评论(0编辑  收藏  举报

导航