给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指定的步长遍历地牢,要求每一步都不可以超过地牢的边界,也不能到达障碍上。地牢的出口可能在任意某个可以通行的位置上。牛牛想知道最坏情况下,他需要多少步才可以离开这个地牢。
在答题之前需要明确本题的题意,第一个是出口的问题,不是边界上的‘.’是出口,而是所有‘.’都可能是出口(除了起始的那个‘.',如果原地不动或者转了一圈之后回到原点,都表示这条路径没有出口,当然如果能转一圈,就一定会经过其他‘.’,则有出口)。第二个是求最大值的问题,将能到达某个‘.’的最短次数记录下来(如何保证最短,这里给定的是跳的长度,跳的最短次数是确定的,广度优先搜索的结果就是最短),在所有的这些能到达各个‘.’的路径中输出最大的次数,即需要移动的次数。需要遍历到所有的‘.’,因为所有的‘.’都可能为出口,我们输出的是最糟糕的情形(原地不动,或者有些‘.’到不了,就输出-1,其他情形则输出移动次数最多的那种)
主要思想是广度优先,代码如下
#include<iostream>
#include<vector>
#include<utility>
#include<algorithm>
#include<queue>
using namespace std;
int main()
{
int n,m,x,y,k; //输入
cin>>n>>m;
vector<vector<char>> ves(n,vector<char>(m,'.'));
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
cin>>ves[i][j];
}
cin>>x>>y;
cin>>k;
using PII=pair<int,int>;
vector<PII> step(k,PII(0,0));
for(int i=0;i<k;i++){
cin>>step[i].first>>step[i].second;
}
//BFS求解
queue<PII> qu;
qu.push(PII(x,y));
vector<vector<int> >reach(n,vector<int>(m,-1));
reach[x][y]=0;
while(!qu.empty()) {
PII temp=qu.front();
qu.pop();
for(int i=0;i<step.size();i++){
int xt=temp.first+step[i].first;
int yt=temp.second+step[i].second;
if(xt>=0&&xt<n&&yt>=0&&yt<m&&ves[xt][yt]=='.'&&reach[xt][yt]==-1){
reach[xt][yt]=reach[temp.first][temp.second]+1;
qu.push(PII(xt,yt));
}
}
}
int maxL=0;
for(int i=0;i<n&&maxL!=-1;i++)
for(int j=0;j<m;j++){
if(reach[i][j]!=-1){
maxL=max(maxL,reach[i][j]);
}else if(ves[i][j]=='.'){
maxL=-1;
break;
}
}
cout<<maxL<<endl;
return 0;
}