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  } 
  • 相关阅读:
    Visual Studio 2010使用Visual Assist X的方法
    SQL Server 2000 评估版 升级到 SQL Server 2000 零售版
    双网卡多网络单主机同时访问
    开发即过程!立此纪念一个IT新名词的诞生
    delphi dxBarManager1 目录遍历 转为RzCheckTree2树
    5320 软件集合
    delphi tree 从一个表复制到另一个表
    DELPHI 排课系统课表
    长沙金思维 出现在GOOGLE的 金思维 相关搜索里啦!!
    如何在DBGrid的每一行前加一个单选框?
  • 原文地址:https://www.cnblogs.com/tflsnoi/p/9739612.html
Copyright © 2011-2022 走看看