第七章 图(POJ3984图的DFS、BFS+记录路径问题)

迷宫问题 POJ - 3984

定义一个二维数组:

int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

【bfs被坑的错误代码】

/*
    这个代码坑了我的点:
    1.print_path函数坑我的点已经注释
    2.最坑的地方是我记录路径的方法,我用next数组来记录路径,
    仔细想想,用脑走一下bfs就知道next是不对的,比如下面这个:
    0 1 1 1 1
    0 1 1 1 1
    0 0 1 1 1
    0 1 1 1 1
    0 0 0 0 0
    如果进队顺序是(0,0),(1,0),(2,0),(3,0),(2,1)这样的话,由
    原来的next[2][0].x=3,next[2][0].y=0变成了next[2][0].x=2,
    next[2][0].y=1,接着继续进队的是(3,0),但是(2,0)和(3,0)
    已经失去了联系。所以还是用pre数组来记录路径是没问题的,
    这里就是一对多改成了多对一,多对一是完全正确的,好似函数
    的概念乎!
    上面的第2个坑点导致了死循环的出现。(next数组是全局的,
    其所有值默认为0)
*/

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

int a[10][10];
bool vis[10][10];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

typedef struct{
    int x,y;
}point;

point next[10][10];

void input();
void bfs();
void print_path();

int main()
{
    input();
    bfs();
    print_path();
    return 0;
}

void input(){
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            cin>>a[i][j];
}

void bfs(){
    memset(vis,0,sizeof(vis));
    point p,q;
    p.x=p.y=0;
    queue<point>que;
    que.push(p);
    vis[p.x][p.y]=1;
    while(!que.empty()){
        if(p.x==4 && p.y==4) break;
        p=que.front();
        que.pop();
        int xx,yy;
        for(int i=0;i<4;i++){
            xx=p.x+dir[i][0];
            yy=p.y+dir[i][1];
            if(xx>=0 && xx<=4 && yy>=0 && yy<=4 && !a[xx][yy] && !vis[xx][yy]){
                q.x=xx;
                q.y=yy;
                que.push(q);
                vis[xx][yy]=1;
                next[p.x][p.y].x=xx;
                next[p.x][p.y].y=yy;
            }
        }
    }
}

void print_path(){
    int x=0,y=0;
    while(!(x==4 && y==4)){
        cout<<"("<<x<<", "<<y<<")"<<endl;
        /*
            坑我的点:
            下面这么写的话,上一个x改变后,影响了下一个式子中的x,导致错误
            x=next[x][y].x;
            y=next[x][y].y;
        */
        int xx=next[x][y].x;
        int yy=next[x][y].y;
        x=xx;
        y=yy;
    }
}


【BFS,ac代码】

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

int a[10][10];
bool vis[10][10];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

typedef struct{
    int x,y;
}point;

point pre[10][10];

void input();
void bfs();
void print_path();

int main()
{
    input();
    bfs();
    print_path();
    return 0;
}

void input(){
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            cin>>a[i][j];
}

void bfs(){
    memset(vis,0,sizeof(vis));
    point p,q;
    p.x=p.y=4;
    queue<point>que;
    que.push(p);
    vis[p.x][p.y]=1;
    while(!que.empty()){
        if(p.x==0 && p.y==0) break;
        p=que.front();
        que.pop();
        int xx,yy;
        for(int i=0;i<4;i++){
            xx=p.x+dir[i][0];
            yy=p.y+dir[i][1];
            if(xx>=0 && xx<=4 && yy>=0 && yy<=4 && !a[xx][yy] && !vis[xx][yy]){
                q.x=xx;
                q.y=yy;
                que.push(q);
                vis[xx][yy]=1;
                pre[xx][yy].x=p.x;
                pre[xx][yy].y=p.y;
            }
        }
    }
}

void print_path(){
    int x=0,y=0;
    while(!(x==4 && y==4)){
        cout<<"("<<x<<", "<<y<<")"<<endl;
        int xx=pre[x][y].x;
        int yy=pre[x][y].y;
        x=xx;
        y=yy;
    }
    cout<<"("<<x<<", "<<y<<")"<<endl;
}

【DFS,ac代码】

#include<iostream>
#include<stack>
#include<cstring>
using namespace std;

int mp[10][10];
bool vis[10][10];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

typedef struct{
    int x,y;
}point;

stack<point>sta;
int mmin=1000;
point path[100];

void input();
void dfs(int x,int y,int step);
void update_path(stack<point>sta);
void print_path();

int main()
{
    input();
    memset(vis,0,sizeof(vis));
    dfs(0,0,1);
    print_path();
    return 0;
}

void input(){
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            cin>>mp[i][j];
}

void dfs(int x,int y,int step){
    point p;p.x=x;p.y=y;
    sta.push(p);
    vis[x][y]=1;
    if(x==4 && y==4){
        if(step<mmin){
            mmin=step;
            update_path(sta);
        }
    }
    //下面循环控制深搜结束(四个方向深搜如下)
    for(int i=0;i<4;i++){
        int xx=x+dir[i][0];
        int yy=y+dir[i][1];
        if(xx>=0 && xx<=4 && yy>=0 && yy<=4 && !mp[xx][yy] && !vis[xx][yy]){
            vis[xx][yy]=1;
            dfs(xx,yy,step+1);
            vis[xx][yy]=0;//走过的路重新标记为0,可以再次走该点
        }
    }
    sta.pop();//对于某点,四个方向都不能走,就退回上一个点,相应路径点出栈
}
//下面函数中注意要带参数,如果没有参数,直接对全局变量sta操作,是明显错误的
void update_path(stack<point>sta){
    for(int i=(int)sta.size();i>=1;i--){
        path[i]=sta.top();
        sta.pop();
    }
}

void print_path(){
    for(int i=1;i<=mmin;i++){
        cout<<"("<<path[i].x<<", "<<path[i].y<<")"<<endl;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值