地牢逃脱

问题描述

http://www.nowcoder.com/questionTerminal/0385945b7d834a99bc0010e67f892e38

给定一个 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次。

输入例子:
3 3



0 1
4
1 0
0 1
-1 0
0 -1

输出例子:
3

笔记

要计算最多多少步才能逃出地牢,要先算出每个位置最快多少步可以到达,然后看哪个位置的步数最多。

使用队列进行BFS搜索,当遇到下一跳的的步数可以变小的时候,把下一跳加入到队列中,然后再继续搜索。

搜索结束后,如果有些点是’.’表示可能是出口,但是又因为各种原因没有遍历到(res[i][j] == inf && map[i][j] == '.')那就说明跑不出去了,输出-1。

代码

//测试用例很奇怪啊//当遇到需要输出-1的时候不是应该break然后处理下一个测试用例吗//竟然是需要输出-1的时候用return结束程序反而可以通过测试。真是醉了。​#include <stdio.h>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int inf = 9999;

void vprint(vector<vector<int> > map)
{
        for (auto i : map)
        {
                for (auto j : i)
                {
                        cout << j << ' ';
                }
                cout << endl;
        }
}

void vprint(vector<vector<char> > map)
{
        for (auto i : map)
        {
                for (auto j : i)
                {
                        cout << j << ' ';
                }
                cout << endl;
        }
}

void solve(vector<vector<char> > map, const int n, const int m, vector<vector<int> > d,
                vector<vector<int> > &res, queue<pair<int, int> > &q)
{
        while (!q.empty())
        {
                pair<int, int> nowp = q.front();
                q.pop();
                for (auto onestep : d)
                {
                        int i = nowp.first;
                        int j = nowp.second;
                        int nexti = i + onestep[0];
                        int nextj = j + onestep[1];
                        if (nexti>=0 && nexti<n && nextj>=0 && nextj<m && map[nexti][nextj] == '.')
                        {
                                if (res[nexti][nextj] > res[i][j] + 1)//只有新的走法比原来小的时候才更新
                                {
                                        res[nexti][nextj] = res[i][j] + 1;
                                        q.push(pair<int, int>(nexti, nextj));
                                        //printf("(%d, %d) -> (%d, %d), res = %d \n", i, j, nexti, nextj, res[nex$
                                }
                        }

                }
        }
}
int main()
{
        int n, m;
        while (cin >> n >> m)
        {
                vector<vector<char> > map;
                for (int i = 0; i < n; i++)
                {
                        vector<char> line;
                        for (int j = 0; j < m; j++)
                        {
                                char tmp;
                                cin >> tmp;
                                line.push_back(tmp);
                        }
                        map.push_back(line);
                }
                int x0, y0, k, dx, dy;
                cin >> x0 >> y0;
                cin >> k;
                vector<vector<int> > d;
                for (int i = 0; i < k; i++)
                {
                        cin >> dx >> dy;
                        vector<int> tmp = {dx, dy};
                        d.push_back(tmp);
                }
                //printf("n = %d, m = %d\n", n, m);
                //vprint(map);
                //printf("x0 = %d, y0 = %d, k = %d\n", x0, y0, k);
                //vprint(d);

                vector<vector<int> > res(n, vector<int>(m, inf));//存储结果的数组
                res[x0][y0] = 0;
                queue<pair<int, int> > q;//BFS的队列
                q.push(pair<int, int>(x0, y0));
                solve(map, n, m, d, res, q);
                //cout << "res\n" << endl;
                //vprint(res);
                int ret = -1;
                for (int i = 0; i < n; i++)
                {
                        for (int j = 0; j < m; j++)
                        {
                                if (res[i][j] == inf && map[i][j] == '.')//原来是'.'但是走不到那里去,返回-1
                                {
                                        cout << -1 << endl;
                                        return 0;
                                }
                                if (res[i][j] != inf)
                                        ret = max(res[i][j], ret);
                        }
                }

                cout << ret << endl;

        }

        return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值