关于 BFS 中 打印路径的问题

打印路径可以用栈的方式, 也可以用递归。

下面看看用递归做的吧

还是NYOJ 最少步数那道题

#include <iostream>
#include<queue>
#include<cstring>
#include<cstdio>
const int dx[4] = {0, 0,-1, 1};
const int dy[4] = {-1,1, 0, 0};
struct node
{
    int x, y;
    int step;
};
int x1, y1, x2, y2;
node now, next;
node S,E;

using namespace std;
bool vis[10][10];
node qq[10][10];
int map[9][9] = {1,1,1,1,1,1,1,1,1
, 1,0,0,1,0,0,1,0,1
 ,1,0,0,1,1,0,0,0,1
 ,1,0,1,0,1,1,0,1,1
 ,1,0,0,0,0,1,0,0,1
 ,1,1,0,1,0,1,0,0,1
 ,1,1,0,1,0,1,0,0,1
 ,1,1,0,1,0,0,0,0,1
 ,1,1,1,1,1,1,1,1,1};
int bfs()
{
    if(S.x == E.x && S.y == E.y)
        return 0;
    memset(vis, false,sizeof(vis));
    queue<node>q;
    q.push(S);
    vis[S.x][S.y] = true;
    while(!q.empty())
    {
        now = q.front();
        q.pop();
        for(int i=0; i<4; i++)
        {
            next.x = now.x + dx[i];
            next.y = now.y + dy[i];
            next.step = now.step + 1;
            if(map[next.x][next.y] == 1||next.x > 9 || next.x<0 || next.y>9 || next.y<0 || vis[next.x][next.y])
                continue;
            vis[next.x][next.y] = true;
            qq[next.x][next.y].x = now.x;
            qq[next.x][next.y].y = now.y;
            q.push(next);
            if(next.x == E.x && next.y == E.y)
                return next.step;
        }
    }
    return -1;

}

void pri(int sx, int sy) {
    if( sx==x1 && sy==y1 ) {
        printf("(%d, %d)\n", sx, sy);
        return ;
    }
    pri(qq[sx][sy].x, qq[sx][sy].y);
    printf("(%d, %d)\n", sx, sy);
}
int main()
{
    int T;

    cin >> T;
    while(T--)
    {
        cin >> x1 >> y1;
        cin >> x2 >> y2;
        S.x = x1;
        S.y = y1;
        S.step = 0;
        E.x = x2;
        E.y = y2;

        int ans = bfs();
        if(ans >= 0)
        {
            cout << ans << endl;
            pri(x2, y2);
        }

    }
    return 0;
}



下面是用栈实现的:

#include <iostream>
#include<queue>
#include<cstring>
#include<stack>
const int dx[4] = {0, 0,-1, 1};
const int dy[4] = {-1,1, 0, 0};
struct node
{
    int x, y;
    int step;
};
int x1, y1, x2, y2;
node now, next;
node S,E;
node Pre[10][10];
using namespace std;
bool vis[10][10];
int map[9][9] = {1,1,1,1,1,1,1,1,1
, 1,0,0,1,0,0,1,0,1
 ,1,0,0,1,1,0,0,0,1
 ,1,0,1,0,1,1,0,1,1
 ,1,0,0,0,0,1,0,0,1
 ,1,1,0,1,0,1,0,0,1
 ,1,1,0,1,0,1,0,0,1
 ,1,1,0,1,0,0,0,0,1
 ,1,1,1,1,1,1,1,1,1};
int bfs()
{
    if(S.x == E.x && S.y == E.y)
        return 0;
    memset(vis, false,sizeof(vis));
    queue<node>q;
    q.push(S);
    vis[S.x][S.y] = true;
    while(!q.empty())
    {
        now = q.front();
        q.pop();
        for(int i=0; i<4; i++)
        {
            next.x = now.x + dx[i];
            next.y = now.y + dy[i];
            next.step = now.step + 1;
            if(map[next.x][next.y] == 1||next.x > 9 || next.x<0 || next.y>9 || next.y<0 || vis[next.x][next.y])
                continue;
            vis[next.x][next.y] = true;
            Pre[next.x][next.y] = now;
            q.push(next);
            if(next.x == E.x && next.y == E.y)
                return next.step;

        }
    }
    return -1;

}
void PrintPath(int row,int column){
    //输出最短路径
    node temp;         //保存位置
    stack<node> s;     //保存路径序列
    temp.x = row;
    temp.y = column;
    while(temp.x != x1 || temp.y != y1){
        s.push(temp);
        temp = Pre[temp.x][temp.y];
    }
    cout<<"(" << x1 << "," << y1 << ")" << endl;
    while(!s.empty()){
        temp = s.top();
        cout<<"("<<temp.x<<","<<temp.y<<")" << endl;
        s.pop();
    }
    cout<<endl;
}
int main()
{
    int T;

    cin >> T;
    while(T--)
    {
        cin >> x1 >> y1;
        cin >> x2 >> y2;
        S.x = x1;
        S.y = y1;
        S.step = 0;
        E.x = x2;
        E.y = y2;

        int ans = bfs();
        if(ans >= 0)
        {
            cout << ans << endl;
            PrintPath(x2, y2);
        }

    }
    return 0;
}
/*
2
3 1  5 7
12
(3,1)
(4,1)
(4,2)
(4,3)
(4,4)
(5,4)
(6,4)
(7,4)
(7,5)
(7,6)
(7,7)
(6,7)
(5,7)

3 1 6 7
11
(3,1)
(4,1)
(4,2)
(4,3)
(4,4)
(5,4)
(6,4)
(7,4)
(7,5)
(7,6)
(7,7)
(6,7)


Process returned 0 (0x0)   execution time : 24.583 s
Press any key to continue.

*/

再做做下面这道题, 越来越发现应该学会融会贯通啊!

题目描述:

一个网格迷宫由n行m列的单元格组成,每个单元格要么是空地(用1表示),要么是障碍物(用0来表示)。你的任务是找一条从起点到终点的最短步数和移动序列,其中UDLR表示上下左右操作。任何时候都不能在障碍物格子中,也不能走到迷宫之外。起点和终点保证都是空地。n,m<100。

样例输入:

6 5

11011

10111

10100

10111

11101

11111

样例输出:

9

DDDDDRRRR

解题思路:

较上一个文章来说,只是多了输出路径,这里既然题目没规定入口出口,为了方便起见,我人为的把入口和出口规定为左上角和右下角。记录路径即需要知道终点是由那个点走到的,而这个点的上一个点也需要知道……所以就记录下每个点的父节点和相应的操作,然而准备输出路径的时候又遇到了一个问题:从出口一步步向上寻找,是一个倒着的,怎么才能正着输出呢?先进后出这个特点是栈对应的特点,而递归类似栈,所以利用递归的方式,达到按顺序输出的目的。

代码:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<cstdio>  
  2. #include<queue>  
  3. #include<iostream>  
  4. using namespace std;  
  5.   
  6. char mmap[10][10]={};  
  7. int vis[10][10]={};  
  8. int n,m;  
  9. int xx[4]={1,0,0,-1};
  10. int yy[4]={0,1,-1,0};  
  11.   
  12. struct node  
  13. {  
  14.     int x,y;  
  15.     int t;
  16. };  
  17.   
  18. struct father  
  19. {  
  20.     int x,y;//当前格子的父节点坐标  
  21.     char cz;//由什么操作到达的这个格子  
  22. };  
  23.   
  24. queue<node> q;  
  25. node s,f;  
  26.   
  27. father lj[10][10];//记录路径  
  28.   
  29. int bfs()  
  30. {  
  31.     int i,j;  
  32.     s.x=0;s.y=0;s.t=0;  
  33.     f.x=n-1;f.y=m-1;  
  34.     q.push(s);  
  35.     lj[s.x][s.y].x=1000;//因为m,n<=100  
  36.     lj[s.x][s.y].y=1000;  
  37.     lj[s.x][s.y].cz=0;  
  38.     vis[s.x][s.y]=1;//标为已经访问过  
  39.   
  40.     while(!q.empty())  
  41.     {  
  42.         node now=q.front();  
  43.         q.pop();  
  44.         for(i=0;i<4;++i)  
  45.         {  
  46.             node New;  
  47.             New.x=now.x+xx[i];  
  48.             New.y=now.y+yy[i];  
  49.             New.t=now.t+1;  
  50.             if(New.x<0||New.y<0||New.x>=n||New.y>=m||vis[New.x][New.y]||mmap[New.x][New.y]=='0')//下标越界或者访问过或者是障碍物  
  51.                 continue;  
  52.   
  53.             q.push(New);  
  54.             lj[New.x][New.y].x=now.x;  
  55.             lj[New.x][New.y].y=now.y;  
  56.             if(i==0)        lj[New.x][New.y].cz='D';  
  57.             else if(i==1)   lj[New.x][New.y].cz='R';  
  58.             else if(i==2)   lj[New.x][New.y].cz='L';  
  59.             else if(i==3)   lj[New.x][New.y].cz='U';  
  60.             vis[New.x][New.y]=1;  
  61.   
  62.             if(New.x==f.x&&New.y==f.y) return New.t;//到达终点  
  63.         }  
  64.     }  
  65.     return -1;  
  66. }  
  67.   
  68. void dfs(int x, int y)  
  69. {  
  70.     if(x==0&&y==0) return;//找到父节点是起点的格子了  
  71.     else  
  72.     dfs(lj[x][y].x,lj[x][y].y);  
  73.     printf("%c",lj[x][y].cz);  
  74. }  
  75.   
  76. int main()  
  77. {  
  78.     int i,j,ans;  
  79.   
  80.     scanf("%d%d",&n,&m);  
  81.     for(i=0;i<n;++i)  
  82.     {  
  83.         scanf("%s",mmap[i]);  
  84.     }  
  85.     ans=bfs();  
  86.     if(ans<0) printf("error");  
  87.     else  
  88.     {  
  89.         printf("%d\n",ans);  
  90.         dfs(n-1,m-1);//从终点开始找他的父节点  
  91.     }  
  92.   
  93.     return 0;  
  94. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值