迷宫全解

相关题连接:

一本通:http://ybt.ssoier.cn:8088/problem_show.php?pid=1215 

小白菜OJ:http://caioj.cn/problem.php?id=1037

 

 

一、DFS写法:

问题一:迷宫是否能走通?(http://ybt.ssoier.cn:8088/problem_show.php?pid=1215 

 

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int n;
 5 char a[200][200]={0};//用于存放迷宫数据,.为可走,#为不可走 
 6 int book[200][200];//用于标记该点是否被访问,0为未被访问,1为已经访问 
 7 int next[4][2]={{0,-1},{-1,0},{0,1},{1,0}};//存储下一步坐标累加数 
 8 int stx, sty, edx, edy;//分别代表迷宫初始位置、目标位置坐标 
 9 bool f;//标记迷宫是否能走通 
10 void dfs(int x, int y)
11 {
12     //如果到达目标坐标,则打印输出,递归出口 
13     if(x==edx&&y==edy) {
14         f=true;
15     }
16     //尝试四方向的邻居坐标 
17     for(int i=0; i<4; i++)
18     {
19         //计算下一个点的坐标 
20         int nx=x+next[i][0];
21         int ny=y+next[i][1];
22  
23         if(nx<0 || nx>n-1 || ny<0 || ny>n-1) continue;//判断是否越界
24         if(book[nx][ny]==0 && a[nx][ny]=='.')
25         {
26             book[nx][ny]=1;//试探 
27             dfs(nx, ny);
28             //book[nx][ny]=0;//回溯 注意此处不需要回溯,否则就会超时
29         } 
30     } 
31 }
32 int main()
33 {
34     int k;
35     scanf("%d",&k);
36     while(k--)
37     {
38         f=false;//刚开始假定迷宫走不通
39         memset(book,0,sizeof(book)); //book初始化为0 
40         scanf("%d",&n);
41         for(int i=0; i<n; i++)
42         for(int j=0; j<n; j++)
43             scanf(" %c",&a[i][j]);//特别注意这个地方%c前有个空格 原因:https://blog.csdn.net/hx1043116928/article/details/79736723 
44         scanf("%d%d",&stx,&sty);
45         scanf("%d%d",&edx,&edy);
46         book[stx][sty]=1;//设定初始值为不可访问,避免形成回路 
47         dfs(stx,sty); //从出发点开始,第一步走起 
48     
49         if(!f)printf("NO\n");
50         else printf("YES\n");   
51     }
52     return 0;
53 }

 

 

 

问题二:有多少种走法?

 

问题三:输出每条走法?

 

问题四:输出最短路径数?(http://bbs.codeaha.com/problem-12032.html

 

 1 #include <cstdio>
 2 int a[51][51],book[51][51];
 3 int next[4][2]= {{0,-1},{-1,0},{0,1},{1,0}};//这里一定要和数学上的坐标进行区分,x,y分别代表行和列
 4 int n, m;//n行m列迷宫 
 5 int min=999999999;//用于存放最短步数,并设定min初始值为一个较大值 
 6 int stx,sty,edx,edy;//分别代表迷宫初始位置、目标位置坐标
 7 bool f=false;//刚开始假定迷宫走不通 
 8 void dfs(int x,int y,int step) {
 9     int nx,ny;//---->>>>注意这一行一定只能写在dfs内<<<<<----- 
10     if(x==edx&&y==edy) {
11         f=true;
12         if(step<min) {
13             min=step;
14         }
15         return ;//判断边界的返回不能丢
16     }
17     for(int i=0; i<=3; i++) {
18         nx=x+next[i][0];
19         ny=y+next[i][1];
20         if(nx<1||nx>n||ny<1||ny>m) {//判断是否越界
21             continue;
22         }
23         if(book[nx][ny]==0&&a[nx][ny]==0) {
24             book[nx][ny]=1;
25             dfs(nx,ny,step+1);
26             book[nx][ny]=0;//收回不能丢
27         }
28     }
29 }
30 int main() {
31     scanf("%d%d",&n,&m);
32     for(int i=1; i<=n; i++) {
33         for(int j=1; j<=m; j++) {
34             scanf("%d",&a[i][j]);
35         }
36     }
37     scanf("%d%d%d%d",&stx,&sty,&edx,&edy);
38     book[stx][sty]=1;//这里就和全排列有点不一样,因为这里进去之后就要发生改变,而全排列进去之后不改变
39     dfs(sty,sty,0);
40     if(!f)printf("No Way!");
41     else printf("%d\n",min);
42     return 0;
43 }

 

二、BFS写法:

 问题一:是否能走通?(http://ybt.ssoier.cn:8088/problem_show.php?pid=1215

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int k, n, ha, la, hb, lb;
 4 char mp[105][105];
 5 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//用二维数组标记上下左右坐标变化 
 6 bool ans;        //答案 
 7 struct node{     //结构体来表示每个位置的坐标 
 8     int x, y;
 9 };
10 node que[10005];//结构体数组模拟队列 
11 int f, r;        //队首队尾 
12 void bfs(){
13     f=r=1;        //初始化队首队尾为1 
14     que[r].x=ha, que[r].y=la, mp[ha][la]='#';//起始点坐标入队,更改状态防止重复访问 
15     while(f<=r){
16         node t;                            //临时变量存放队首信息 
17         t.x=que[f].x, t.y=que[f].y;
18         if(t.x==hb && t.y==lb){            //如果找到目标退出循环 
19             ans=1; 
20             break;
21         }
22         for(int i=0; i<4; i++){            //以队首位置 上下左右四个方向遍历 
23             int nx=t.x+dir[i][0];        
24             int ny=t.y+dir[i][1];
25             if(nx>=0 && nx<n && ny>=0 && ny<n && mp[nx][ny]=='.'){//判断是否符合入队条件 
26                 mp[nx][ny]='#';            //更改状态 
27                 r++;                    //队尾位置后移为入队做准备 
28                 que[r].x=nx;            //行号入队 
29                 que[r].y=ny;            //列号入队 
30             }
31         }
32         f++;                            //队首出队 
33     }
34 }
35 int main()
36 {
37     cin>>k;
38     while(k--){
39         cin>>n;
40         for(int i=0; i<n; i++)
41             cin>>mp[i];
42         cin>>ha>>la>>hb>>lb;
43         ans=0;
44         bfs();
45         if(ans)cout<<"YES"<<endl;
46         else cout<<"NO"<<endl;
47     }
48     return 0;
49 } 

 问题二:最短步骤数(题目连接http://ybt.ssoier.cn:8088/problem_show.php?pid=1252

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int r, c;
 4 char mp[45][45];
 5 struct node{
 6     int x, y, step;
 7 };
 8 int fx, fy, fstep;
 9 node que[2500];
10 int front, rear;
11 int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
12 void bfs()
13 {
14     front=rear=1;
15     que[rear].x=0;  que[rear].y=0; //初始位置入队 
16     que[rear].step=1; 
17     mp[0][0]='#';
18     while(front<=rear){
19         fx=que[front].x; fy=que[front].y; fstep=que[front].step;  //获取队首信息 
20         if(fx==r-1 && fy==c-1){
21             cout<<fstep<<endl;
22             break;
23         }
24         for(int i=0; i<4; i++){
25             int nx=fx+dir[i][0];
26             int ny=fy+dir[i][1];
27             if(nx>=0 && nx<r && ny>=0 && ny<c && mp[nx][ny]=='.'){
28                 mp[nx][ny]='#';
29                 rear++;                        //队尾位置后移准备入队 
30                 que[rear].x=nx;                //入队 
31                 que[rear].y=ny;                //入队 
32                 que[rear].step=fstep+1;        //步数加1 
33             }
34         }
35         front++;                            //队首后移出队 
36     }
37 }
38 int main()
39 {
40     cin>>r>>c;
41     for(int i=0; i<r; i++)cin>>mp[i];
42     bfs();
43     return 0;
44  } 

 问题三:最少需要走的步数(同问题二)(http://ybt.ssoier.cn:8088/problem_show.php?pid=1254

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n, m;
 4 char mp[105][105];
 5 int sx, sy, tx, ty;
 6 struct node{                    //结构体定义位置坐标和起点开始步骤 
 7     int x, y, step;
 8 };
 9 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};        //二维数组定义上下左右方向位移量 
10 node que[10010];    //结构体数组存放队列 
11 int f, r;            //队首和队尾定义 
12 void bfs(){
13     f=r=1;            //队列初始化 
14     que[r].x=sx; que[r].y=sy; que[r].step=0; mp[sx][sy]='#';//初始位置入队 
15     while(f<=r){
16         int fx=que[f].x,   fy=que[f].y, fs=que[f].step;//获取队首信息 
17         if(fx==tx && fy==ty){//判断是否到达目标 
18             cout<<fs;
19             break;
20         }
21         for(int i=0; i<4; i++){//遍历四个方向 
22             int nx=fx+dir[i][0];
23             int ny=fy+dir[i][1];
24             if(nx>=0 && nx<n && ny>=0 && ny<m && (mp[nx][ny]=='.' || mp[nx][ny]=='T')){//判断是否满足入队条件 ,注意此处终点排除‘T’ 
25                 mp[nx][ny]='#';//更改状态避免重复入队 
26                 r++;//队尾后移准备入队 
27                 que[r].x=nx;//入队 
28                 que[r].y=ny;
29                 que[r].step=fs+1;//步骤加1 
30             }
31         }
32         f++;//队首后移出队 
33     }
34 }
35 int main()
36 {
37     cin>>n>>m;
38     for(int i=0; i<n; i++)
39         cin>>mp[i];
40     for(int i=0; i<n; i++)
41         for(int j=0; j<m; j++){
42             if(mp[i][j]=='S'){
43                 sx=i; sy=j;
44             }
45             if(mp[i][j]=='T'){
46                 tx=i; ty=j;
47             }
48         }
49     bfs();
50     return 0;
51  } 

 

问题四:输出最短路径(http://ybt.ssoier.cn:8088/problem_show.php?pid=1255

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int maze[5][5];
 4 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
 5 struct node{            //结构体表示位置坐标,以及该位置是从哪个点过来的 
 6     int x, y, from;
 7 };
 8 node que[30];            //结构体数组来表示队列 
 9 int f, r;                //队首队尾 
10 void pr(int p){            //递归顺序打印路线 
11     if(p==0)
12         return;
13     pr(que[p].from);
14     cout<<"("<<que[p].x<<", "<<que[p].y<<")"<<endl;
15 }
16 void pr2(){
17     for(int i=f; i ; i=que[i].from)                //逆着打印路线和pr()函数对比 
18         cout<<"("<<que[i].x<<", "<<que[i].y<<")"<<endl;
19 }
20 void bfs()
21 {
22     f=r=1;//队列初始 
23     que[r].x=0; que[r].y=0; que[r].from=0; maze[0][0]=1; //起始点入队 
24     while(f<=r){
25         int fx=que[f].x;            //获取队首信息 
26         int fy=que[f].y;            //获取队首信息
27         if(fx==4 && fy==4)pr(f);    //如果到达目标打印路径 
28         for(int i=0; i<4; i++){
29             int nx=fx+dir[i][0];
30             int ny=fy+dir[i][1];
31             if(nx>=0 && nx<5 && ny>=0 && ny<5 && maze[nx][ny]==0){
32                 maze[nx][ny]=1;
33                 r++;                //队尾后移准备入队 
34                 que[r].x=nx;        //入队 
35                 que[r].y=ny;        //入队 
36                 que[r].from=f;        //入队坐标的爸爸是谁 
37             }
38         }
39         f++;
40     }
41 }
42 int main()
43 {
44     for(int i=0; i<5; i++)
45         for(int j=0; j<5; j++)
46             cin>>maze[i][j];
47     bfs();
48     return 0;
49  } 

 

posted @ 2018-10-03 13:12  TFLSNOI  阅读(453)  评论(0编辑  收藏  举报