zoukankan      html  css  js  c++  java
  • 迷宫全解

    相关题连接:

    一本通: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
    ");
    50         else printf("YES
    ");   
    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
    ",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  } 
  • 相关阅读:
    Android Studio教程-创建第一个项目Hello World
    java打jar包的几种方式详解
    低学历者如何逆袭
    strlen, wcslen, _mbslen, _mbslen_l, _mbstrlen, _mbstrlen_l, setlocale(LC_CTYPE, "Japanese_Japan")(MSDN的官方示例)
    select, poll, epoll
    KVM虚拟化知识的一些笔记
    在Windows系统上以C++打印出当前活动用户的环境变量
    日志组件解析
    Angular2案例rebirth开源
    视图
  • 原文地址:https://www.cnblogs.com/tflsnoi/p/9739612.html
Copyright © 2011-2022 走看看