BFS入门经典(天神小学)外加队列基础讲解

天神小学
时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte
总提交 : 145 测试通过 : 50

题目描述
《corpse party:blood drive》中有这么一段,班长筱崎亚由美拿到六鬼门的晶石,导致了涅的暴走,天小的崩溃,靠着幸子的力量才逃出了天小。(剧情什么的不重要)
现在我们假设没有幸子,班长需要靠自己的力量逃出天神小学。可以把天神小学看作是一个二维的迷宫,每一秒都只能从当前位置走到上下左右四个相邻的格子里,因为天小一直在崩溃,所以有很多点是无法行走的。问班长能不能在天小完全崩溃,即t秒内逃出天神小学。

输入
第一行一个整数T,表示数据组数
每组数据第一行输入3个整数n,m,t分别表示迷宫的行数,列数,以及距离天小崩溃剩余的时间。(3≤n,m≤20,t≤100)
接下来输入n行,每行有一个长度为m的字符串。
其中字符’.’表示可以通行
字符’*’表示无法通行
字符’O’表示出口
字符’X’表示班长的起始位置

输出
若能逃离 输出 “happy end”
否则输出 “bad end”

样例输入
2
5 5 13
…..
.*.
.*X*O
...
…*.

5 5 14
…..
.*.
.*X*O
...
…*.

样例输出
bad end
happy end

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
const int lim=50;
using namespace std;
int dirx[4]= {-1, 1, 0, 0};
int diry[4]= {0, 0, -1, 1};
int row, col, time;
char Map[lim][lim];
int vis[lim][lim];
char str[300];
int xru, yru, xchu, ychu;
struct point
{
    int x;
    int y;
    int step;
};
void bfs();
int main ()
{
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    int i, j, T;
    cin>>T;
    while(T--)
    {
        cin>>row>>col>>time;  
        memset(str, 0, sizeof(str));
        memset(Map, 0, sizeof(Map));
        memset(vis, 0, sizeof(vis));
        for(i=1; i<=row; i++)
        {
            scanf("%s", str);
            for(j=1; j<=col; j++)
                Map[i][j]=str[j-1];
        }
        for(i=1; i<=row; i++)
            for(j=1; j<=col; j++)
            {
                if(Map[i][j]=='X')
                {
                    xru=j;
                    yru=i;
                }
            }
        for(i=1; i<=row; i++)
            for(j=1; j<=col; j++)
            {
                if(Map[i][j]=='O')
                {
                    xchu=j;
                    ychu=i;
                }
            }
        bfs();
    }
    return 0;
}

void bfs()
{
    int i, j;
    vis[xru][yru]=1;
    point node, t;
    queue<point> q;
    node.x=xru;
    node.y=yru;
    node.step=0;
    q.push(node);
    while(!q.empty())
    {
        node=q.front();
        q.pop();
        for(i=0; i<4; i++)
        {
            t=node;
            t.x+=dirx[i];
            t.y+=diry[i];
            t.step++;
            if(t.x==xchu&&t.y==ychu)
            {

                printf("%s", t.step<=time?"happy end\n":"bad end\n");
                return;
            }
            if(t.x<1||t.x>col||t.y<1||t.y>row||Map[t.y][t.x]=='*'||vis[t.y][t.x])
                continue;
            else
            {
                vis[t.y][t.x]=1;
                q.push(t);
            }
        }
    }
    printf("bad end\n");
    return;
}
这是我校去年网络赛的一道题,就是bfs模板题。 用队列先进先出的特点。(队列就像一个两边通的胡同,先进的汽车先出,而栈就像一个死胡同,先进去的汽车后出来) 

其实对还没有接触C++的同学,这代码看着有点难以理解,但是语言就是语言,没有思维含量,记住语法规则就可以了。
要使用队列,首先要包含头文件 ,于是#include 。就像int变量一样,我们要声明一个队列,queue q;
声明了一个我们自定义的point的一个队列。
q.pop() 出队 如q.pop(t) 把队列里第一个元素t给“踢”出去
q.push() 入队 如q.push(t) 把一个元素t给“请”到队伍的最后。
q.front() 看用法自己体会 如t=q.front(t),就是把队列里的第一个元素赋给t。
q.empty() 如果队列为空,则返回true,否则返回false
q.size()返回队列中的元素的个数,因此用q.size == 0 也是用来判断对象是否为空的办法。
一般基础的深搜求最小连通块(也叫种子填充算法,维基百科种子填充词条有GIF动画,大家可以看一看),广搜求最短路径。
大家可以手动模拟程序运行来理解bfs模板

你可能感兴趣的:(bfs)