问题描述
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;
}