bfs培训例题题解


迷宫问题
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 30441   Accepted: 17504

Description

定义一个二维数组: 
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,路径打印就一个简单的递归。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
int to[4][2]= {0,1,0,-1,1,0,-1,0};
int mapp[6][6];
int direct[6][6];
struct node
{
    int x,y;
    node () {};
    node (int a,int b)
    {
        x=a;
        y=b;
    }
};

int check(int x,int y)
{
    if(x<0||x>=5||y<0||y>=5||mapp[x][y])
        return 0;
    return 1;
}

void print(int x,int y)
{
    if(direct[x][y]==-1)
    {
        printf("(%d, %d)\n",x,y);
        return ;
    }
    int i=direct[x][y];
    print(x-to[i][0],y-to[i][1]);
    printf("(%d, %d)\n",x,y);
}

void bfs()
{
    node t(0,0);
    queue<node>q;
    q.push(t);
    direct[0][0]=-1;
    mapp[0][0]=1;
    while(!q.empty())
    {
        node it=q.front();
        q.pop();
        if(it.x==4&&it.y==4)
        {
            print(4,4);
            return ;
        }
        for (int i=0; i<4; i++)
        {
            int xx=it.x+to[i][0];
            int yy=it.y+to[i][1];
            node next(xx,yy);
            if(check(xx,yy))
            {
                direct[xx][yy]=i;//记录每个位置来的方向
                mapp[xx][yy]=1;
                q.push(next);
            }
        }
    }
}
int main ()
{
    for (int i=0; i<5; i++)
        for (int j=0; j<5; j++)
            cin>>mapp[i][j];
    bfs();
    return 0;
}




迷宫寻宝(一)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述

一个叫ACM的寻宝者找到了一个藏宝图,它根据藏宝图找到了一个迷宫,这是一个很特别的迷宫,迷宫里有N个编过号的门(N<=5),它们分别被编号为A,B,C,D,E.为了找到宝藏,ACM必须打开门,但是,开门之前必须在迷宫里找到这个打开这个门所需的所有钥匙(每个门都至少有一把钥匙),例如:现在A门有三把钥匙,ACM就必须找全三把钥匙才能打开A门。现在请你编写一个程序来告诉ACM,他能不能顺利的得到宝藏。

输入
输入可能会有多组测试数据(不超过10组)。
每组测试数据的第一行包含了两个整数M,N(1<N,M<20),分别代表了迷宫的行和列。接下来的M每行有N个字符,描述了迷宫的布局。其中每个字符的含义如下:
.表示可以走的路
S:表示ACM的出发点
G表示宝藏的位置
X表示这里有墙,ACM无法进入或者穿过。
A,B,C,D,E表示这里是门,a,b,c,d,e表示对应大写字母的门上的钥匙。
注意ACM只能在迷宫里向上下左右四个方向移动。

最后,输入0 0表示输入结束。
输出
每行输出一个YES表示ACM能找到宝藏,输出NO表示ACM找不到宝藏。
样例输入
4 4 
S.X. 
a.X. 
..XG 
.... 
3 4 
S.Xa 
.aXB 
b.AG 
0 0
样例输出
YES 
NO


题解:我们先统计整个地图所有不同钥匙的各自的个数,在遍历的过程中自然有机会收集钥匙,若收集全某类钥匙就可以打开此类的门才可以进一步的遍历,直至找到宝藏。

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
int n,m,str[6];
int to[4][2]= {0,1,0,-1,1,0,-1,0};
char mapp[25][25];
int vis[25][25];
struct node
{
    int x,y;
    node () {};
    node (int a,int b)
    {
        x=a;
        y=b;
    }
} ;
int check(int x,int y)
{
    if(x<0||x>=n||y<0||y>=m||vis[x][y]||mapp[x][y]=='X')
        return 0;
    return 1;
}
int bfs(int x,int y)
{
    node t(x,y);
    queue<node>q;
    q.push(t);
    vis[x][y]=1;
    while(!q.empty())
    {
        node it=q.front();
        q.pop();
        char ch=mapp[it.x][it.y];
        if(ch>='A'&&ch<='E')//如果是门
        {
            if(str[ch-'A'])//钥匙没收集全。若收集全了就可以通过此门。
            {
                if(q.empty())//能走的地方都搜过了(已经没有之外的可以走了),而且没找到宝藏。
                    return 0;
                q.push(it);//还有其他地方没搜,所以再次放队列中,等搜集全钥匙再来开门。
                continue;
            }
        }
        for (int i=0; i<4; i++)
        {
            int xx=it.x+to[i][0];
            int yy=it.y+to[i][1];
            node tt(xx,yy);
            char ch=mapp[xx][yy];
            if(check(xx,yy))
            {
                if(ch>='a'&&ch<='e')//遇见钥匙
                    str[ch-'a']--;
                else if(ch=='G')//遇见宝藏,直接返回1
                    return 1;
                vis[xx][yy]=1;
                q.push(tt);
            }
        }
    }

    return 0;
}

int main ()
{
    while(cin>>n>>m&&n+m)
    {
        memset(str,0,sizeof(str));
        memset(vis,0,sizeof(vis));
        for (int i=0; i<n; i++)
            cin>>mapp[i];
        int sx=0,sy=0;
        for (int i=0; i<n; i++)
            for (int j=0; j<m; j++)
                if(mapp[i][j]=='S')
                {
                    sx=i;
                    sy=j;
                }
                else if(mapp[i][j]>='a'&&mapp[i][j]<='e')//统计出整个地图中不同钥匙的各自数量。
                    str[mapp[i][j]-'a']++;
        if(bfs(sx,sy))
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}




猜你喜欢

转载自blog.csdn.net/zero_zp/article/details/80216011
今日推荐