2017 校招题目 地牢逃脱 考察 BFS

题目描述

给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指定的步长遍历地牢,要求每一步都不可以超过地牢的边界,也不能到达障碍上。地牢的出口可能在任意某个可以通行的位置上。牛牛想知道最坏情况下,他需要多少步才可以离开这个地牢。

输入描述:

每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 50),表示地牢的长和宽。接下来的 n 行,每行 m 个字符,描述地牢,地牢将至少包含两个 '.'。接下来的一行,包含两个整数 x0, y0,表示牛牛的出发位置(0 <= x0 < n, 0 <= y0 < m,左上角的坐标为 (0, 0),出发位置一定是 '.')。之后的一行包含一个整数 k(0 < k <= 50)表示牛牛合法的步长数,接下来的 k 行,每行两个整数 dx, dy 表示每次可选择移动的行和列步长(-50 <= dx, dy <= 50)

输出描述:

输出一行一个数字表示最坏情况下需要多少次移动可以离开地牢,如果永远无法离开,输出 -1。以下测试用例中,牛牛可以上下左右移动,在所有可通行的位置.上,地牢出口如果被设置在右下角,牛牛想离开需要移动的次数最多,为3次。

示例1

输入

复制

3 3
...
...
...
0 1
4
1 0
0 1
-1 0
0 -1

输出

复制

3

思路:要用一个队列来遍历 保存 某个点的周围的点;

出队 将新的点入队;改变step[i][j]的值;

d[k][2]在这里用点的方式存储;

vector<Position>pos;//构建一个数组;

    for(int i=0;i<K;i++)

    {

        int x,y;

        cin>>x>>y;

        pos.emplace_back(x,y);

    }

代码:

#include<iostream>
#include <vector>//容器;
#include <assert.h>//断言
#include<ctime>//时间
#include<cmath>//数学
#include <string>//字符串
#include <algorithm>//算法头文件;
#include<map>
#include<set>
#include<limits.h>
#include<queue>
using namespace std;
using ll=long long;
int n,m;
vector<vector<char>>gra;
struct Point
{
    int x,y;
    Point(int X,int Y):x(X),y(Y){};
    bool isOk(){return x>=0&&x<n&&y>=0&&y<m&&gra[x][y]=='.';}
    Point add(Point &p){return Point(x+p.x,y+p.y);}
};
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        vector<char>temp(m);
        for(int j=0;j<m;j++)
            cin>>temp[j];
        gra.push_back(temp);
    }
    int x0,y0;
    cin>>x0>>y0;
    Point P0(x0,y0);
    int K;
    cin>>K;
    vector<Point>pos;//构建一个数组表示他的邻接点;
    for(int i=0;i<K;i++)
    {
        int dx,dy;
        cin>>dx>>dy;
        pos.emplace_back(dx,dy);
    }
    vector<vector<int>>step(50,vector<int>(50,100));//表示的是一个 走的步数的数组;
    step[x0][y0]=0;//注意起始点的值 应该为0;
    queue<Point>queue;
    queue.push(P0);
    while(queue.size())
    {
        auto cur=queue.front();
        queue.pop();
        for(int i=0;i<K;i++)
        {
            auto next=cur.add(pos[i]);
            if(next.isOk()&&step[cur.x][cur.y]+1<step[next.x][next.y])
            {
                step[next.x][next.y]=step[cur.x][cur.y]+1;
                queue.push(next);
            }
        }
    }
    int res=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(gra[i][j]=='.')
                res=max(res,step[i][j]);
        }
    }
    if(res==100)
        cout<<-1<<endl;
    else 
        cout<<res<<endl;
    return 0;
}

注意 bfs 与dfs的比较

1、二维数组的题目 当N小于20的适用于dfs  当N《=200 N<=1000的 一定不能用dfs;不仅仅是整个题目不能用dfs  其中的每一步 都不能用dfs;

BFS的基本步骤

  • 将初始点(一个或多个)加入到集合尾;
  • 从集合(队列)头去取出点,判断初始点的周边店,将符合条件的点加入到队列中
  • 重复二操作 直到集合为空;(一般每一个点智能加入队列一次);

一般来说能用dfs解决的问题都能用bfs来解决;

dfs(深度搜索的同时 考虑回溯)

BFS=队列、入队、出队;搜索到的一定是最优解

DFS=栈、压栈、出栈;搜索到的不一定是最优解; 一般情况下需要剪枝操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值