有关dfsbfs解决迷宫问题的个人见解

Posted xdu-lakers

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有关dfsbfs解决迷宫问题的个人见解相关的知识,希望对你有一定的参考价值。

可以使用BFS或者DFS方法解决的迷宫问题!

题目如下:

kotori在一个n*m迷宫里,迷宫的最外层被岩浆淹没,无法涉足,迷宫内有k个出口。kotori只能上下左右四个方向移动。她想知道有多少出口是她能到达的,最近的出口离她有多远?

输入描述:

第一行为两个整数n和m,代表迷宫的行和列数 (1≤n,m≤30)

后面紧跟着n行长度为m的字符串来描述迷宫。‘k‘代表kotori开始的位置,‘.‘代表道路,‘*‘代表墙壁,‘e‘代表出口。保证输入合法。

输出描述:

若有出口可以抵达,则输出2个整数,第一个代表kotori可选择的出口的数量,第二个代表kotori到最近的出口的步数。(注意,kotori到达出口一定会离开迷宫)

若没有出口可以抵达,则输出-1。
示例1

输入

复制
6 8
e.*.*e.*
.**.*.*e
..*k**..
***.*.e*
.**.*.**
*......e

输出

复制
2 7

说明

可供选择坐标为[4,7]和[6,8],到kotori的距离分别是8和7步。


DFS解决如下:
 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 char map[100][100];
 5 int use[100][100];
 6 int dir[4][2] = 0,1,1,0,0,-1,-1,0; //上下左右四个方向
 7 int minn = 999999999;
 8 
 9 int pan(int x,int y)
10 
11     if(0 <= x && x <= 5 && 0 <= y && y <= 7 && (map[x][y] == . || map[x][y]==k)) return 1;
12     else return 0;
13 
14 
15 void dfs(int x,int y,int step)
16 
17     // 递归程序,必须要设置整个程序的出口,在dfs中,即当走到迷宫出口处即可结束程序
18     if(map[x][y] == e)
19     
20         cout<<"success"<<endl;
21         if(step < minn) minn = step;
22         return;
23     
24     for(int i = 0; i < 4; i++)
25     
26         if(pan(x,y) && use[x][y] != 1) 
27         
28             use[x][y] = 1;
29             cout<<"dd";
30             cout<<"  "<<map[x+dir[i][0]][y+dir[i][1]]<<endl;
31             dfs(x+dir[i][0],y+dir[i][1],step+1);
32             use[x][y] = 0;
33                 
34     
35 
36 
37 int main()
38 
39     int n;
40     int m;
41     cin >> n >> m;
42     // 4,5行已经定义了map和use数据,所以在此处不必int map[n][m],直接map[n][m]即可,否则报错 
43     map[n][m];
44     use[n][m];
45     memset(use,0,sizeof(use));
46     int x_start = 0;
47     int y_start = 0;
48     int step = 0;
49     for(int i = 0; i < n; i++)
50     
51         for(int j = 0; j < m; j++)
52         
53             cin >> map[i][j];
54             if(map[i][j] == k)
55             
56                 x_start = i;
57                 y_start = j;
58             
59         
60     
61     cout<<x_start<<" "<<y_start<<endl;
62     dfs(x_start, y_start, step);
63     cout<<"最小步数"<<minn<<endl;
64  

技术图片

 

 

 

BFS解决如下:

(1)自己写的有缺陷的代码:

 1 #include<iostream>
 2 #include<queue>
 3 #include<string.h>
 4 using namespace std;
 5 char map[100][100];
 6 int vis[100][100];
 7 int use[100][100];
 8 int m,n;
 9 int x_start,y_start;
10 queue<int> que;
11 int dir[4][2] = 0,1,0,-1,1,0,-1,0;
12 int cnt = 0;
13 int mi = 999999;
14 
15 int pan(int x,int y)
16 
17     if(0 <= x && x <= n-1 && 0 <= y && y <= m -1 &&map[x][y] != *) return 1;
18     else return 0;
19 
20 
21 void bfs(int x,int y)
22 
23     int x1 = x;
24     int y1 = y;
25     while(!que.empty())
26     
27         vis[x1][y1] = 1;
28         x1 = que.front();
29         que.pop();
30         y1 = que.front();
31         que.pop(); 
32         cout<<"x1:"<<x1<<" "<<"y1:"<<y1<<endl; 
33         if(map[x1][y1] == e)
34         
35             if(use[x1][y1] == 0)
36             
37                 cnt++;
38                 use[x1][y1]=1;
39             
40             continue;
41         
42 
43         for(int i = 0; i < 4; i++)
44         
45             int xx = x1 + dir[i][0];
46             int yy = y1 + dir[i][1];
47             if(pan(xx,yy) && vis[xx][yy] == 0)
48             
49                 cout<<"dd"<<endl;
50                 cout<<xx<<" "<<yy<<endl;
51                 que.push(xx);
52                 que.push(yy);
53                 vis[xx][yy] = 1;
54             
55             
56         
57 
58 
59 int main()
60 
61     memset(vis,0,sizeof(vis));
62     memset(use,0,sizeof(use));
63     cin >> n >> m;
64     for(int i = 0; i < n; i++)
65     
66         for(int j = 0; j < m; j++)
67         
68             cin >> map[i][j];
69             if(map[i][j] == k)
70             
71                 x_start = i;
72                 y_start = j;
73             
74         
75     
76     que.push(x_start);
77     que.push(y_start);
78     bfs(x_start,y_start);
79     cout<<cnt<<endl;
80 
81  

对于每个点每个状态我采用的是直接利用队列记录他们的坐标值,而不是如AC代码一样利用结构体记录每个点的每个状态。所以导致我整个程序还是存在很大的缺陷,例如求最短路径的时候就比较困难。

所以对于BFS的题目,强烈建议把每个点每个状态先用结构体表示,然后利用队列记录这些结构体即可。

(2)AC代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char a[35][35];
 4 bool usd[35][35];
 5 int Move[4][2]=0,1,1,0,-1,0,0,-1;
 6 struct now
 7 
 8     int x,y,dis;
 9 ;
10 queue<now>q;
11 int main()
12 
13     int n,m,cnt=0;
14     scanf("%d%d",&n,&m);
15     now s;
16     for(int i=1;i<=n;++i)
17         for(int j=1;j<=m;++j)
18         
19             cin>>a[i][j];
20             if(a[i][j]==k)
21             
22                 s.x=i;
23                 s.y=j;
24                 s.dis=0;
25             
26         
27     q.push(s);
28     int ans=99999999;
29     while(!q.empty())
30     
31         now Now=q.front();
32         q.pop();
33         if(a[Now.x][Now.y]==e)
34         
35             if(!usd[Now.x][Now.y])
36             
37                 ++cnt;
38                 ans=min(ans,Now.dis);
39             
40             usd[Now.x][Now.y]=true;
41             continue; //到达出口"e"处就必须跳过一下步骤,不能在对出口点“e”进行下面的扩展步骤(上下左右)
42         
43         usd[Now.x][Now.y]=true;
44         for(int i=0;i<4;++i)
45         
46             int xx=Now.x+Move[i][0],yy=Now.y+Move[i][1],d=Now.dis;
47             if(xx<=n&&xx>=1&&yy>=1&&yy<=m&&!usd[xx][yy]&&a[xx][yy]!=*)
48             
49                 now t;
50                 t.x=xx;
51                 t.y=yy;
52                 t.dis=d+1;
53                 q.push(t);
54             
55         
56     
57     if(!cnt)
58         return !printf("-1\\n");
59     printf("%d %d\\n",cnt,ans);
60     return 0;
61 

技术图片

 带路径输出的BFS(路径的输出主要依靠递归程序,记录每个点的结构体还需要记录每个点的前驱节点的坐标)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char a[35][35];
 4 bool usd[35][35];
 5 int Move[4][2]=0,1,1,0,-1,0,0,-1;
 6 struct now
 7 
 8     int x,y,dis,pre_x,pre_y;
 9 ;
10 queue<now>q;
11 now buf[35];
12 int count1 = 0;
13 
14 void print(int x,int y)
15 
16     int temp;
17     for(int i = 0; i < count1; i++)
18     
19         if(buf[i].x == x && buf[i].y == y) temp = i;
20     
21     if(x == -1 && y == -1) return;
22     else
23     
24         print(buf[temp].pre_x,buf[temp].pre_y);
25         cout<<"("<<x<<","<<y<<")"<<endl;
26     
27 
28 
29 int main()
30 
31     int n,m,cnt=0;
32     scanf("%d%d",&n,&m);
33     now s;
34     for(int i=1;i<=n;++i)
35         for(int j=1;j<=m;++j)
36         
37             cin>>a[i][j];
38             if(a[i][j]==k)
39             
40                 s.x=i;
41                 s.y=j;
42                 s.pre_x = -1;
43                 s.pre_y = -1;
44                 s.dis=0;
45             
46         
47     q.push(s);
48     int ans=99999999;
49     while(!q.empty())
50     
51         now Now=q.front();
52         buf[count1++] = Now;
53         q.pop();
54         if(a[Now.x][Now.y]==e)
55         
56             if(!usd[Now.x][Now.y])
57             
58                 ++cnt;
59                 ans=min(ans,Now.dis);
60                 usd[Now.x][Now.y]=true;
61                 print(Now.x,Now.y);
62             
63             continue;
64         
65         usd[Now.x][Now.y]=true;
66         for(int i=0;i<4;++i)
67         
68             int xx=Now.x+Move[i][0],yy=Now.y+Move[i][1],d=Now.dis;
69             if(xx<=n&&xx>=1&&yy>=1&&yy<=m&&!usd[xx][yy]&&a[xx][yy]!=*)
70             
71                 now t;
72                 t.x=xx;
73                 t.y=yy;
74                 t.pre_x = Now.x;
75                 t.pre_y = Now.y;
76                 t.dis=d+1;
77                 q.push(t);
78             
79         
80     
81     if(!cnt)
82         return !printf("-1\\n");
83     printf("%d %d\\n",cnt,ans);
84 //    for(int i = 0; i < count1; i++)
85 //    
86 //        cout<<buf[i].x<<" "<<buf[i].y<<" "<<buf[i].pre_x<<" "<<buf[i].pre_y<<endl;
87 //    
88     return 0;
89 

 

以上是关于有关dfsbfs解决迷宫问题的个人见解的主要内容,如果未能解决你的问题,请参考以下文章

Python 解决一个简单的迷宫问题 在线等

递归--迷宫问题(Java)

迷宫问题

有关搜索和深度优先搜索的浅陋见解

经典迷宫问题

经典迷宫问题