题目链接:https://codeforces.com/gym/103488/problem/F?mobile=true
Kyooma有一把剑,他喜欢使用这把剑与别人击剑。有一天,他的剑突然传送走了,于是Kyooma开始寻找他的剑。
经过长途跋涉,Kyooma终于来到了一个迷宫的门口。他知道自己的剑一定在迷宫的某个地方,但他的剑可以在这个迷宫中瞬移!
现在,Kyooma向你寻求帮助。请告诉他是否能找到剑,因为你可以通过你的特殊能力 未来视 预测在接下来的kk分钟内剑会在哪里。
迷宫由n行m列的方格组成,Kyooma每分钟可以向上、下、左、右移动到相邻的方格,或者什么也不做。Kyooma在第0分钟处于起始位置。
Kyooma不能穿过墙壁或爬上墙壁, 但他可以到达剑出现的位置并等待剑出现。
注意剑可以出现在墙壁上方,并且剑会在第k−1分钟结束后永久传送离开迷宫,这意味着Kyooma将永远无法找到他的剑!
Input
输入的第一行包含一个整数 t(1≤t≤100),表示接下来有tt组测试。
每个测试用例的第一行包含两个整数 n 和 m (1≤n,m≤100)。
接下来 n 行每行包含m个字符,表示Kyooma所在的迷宫。 并且这些迷宫中的字符中的每一个都是以下字符之一:
- '#' — 表示当前格是一堵墙
- '.' — 表示当前格是一个空地
- 'H' — 表示Kyooma在迷宫中的初始位置, 而且这是一个空地
题目保证每组测试用例中都有且只有一个 'H'。
下一行包含一个整数k(1≤k≤n×m),即你预测了接下来kk分钟剑的位置。
之后k行每行包含两个整数x,y(1≤x≤n,1≤y≤m),表示从第0分钟到第k−1分钟剑的位置。
Output
对于每组测试数据单独输出一行。
如果Kyooma可以成功找到他的剑,输出"YES"(不包含引号)和 他最快能找到剑的时刻,用空格分隔。否则,输出"NO"(不包含引号)。
解题思路:先求出到每个位置的时间,再进行比较,如果比剑先到达某个位置,则这个位置可能是答案,再找出用时最少的答案。
#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
int nex[4][2]={1,0,-1,0,0,1,0,-1};
int sx,sy;
struct node
{
int x,y,step;
};
void solve()
{
int n,m;
cin>>n>>m;
char str[200][200];
for(int i=0;i<n;i++)
cin>>str[i];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(str[i][j]=='H')
sx=i,sy=j;
int a[200][200];
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
a[i][j]=-1;
queue<node>zheng;
node r;
r.step=0,r.x=sx,r.y=sy;
zheng.push(r);
a[sx][sy]=0;
while(!zheng.empty())
{
node t=zheng.front();
zheng.pop();
int x=t.x,y=t.y,step=t.step;
for(int i=0;i<4;i++)
{
int nx=x+nex[i][0];
int ny=y+nex[i][1];
if(nx<0||ny<0||nx>=n||ny>=m)
continue;
if(str[nx][ny]=='#'||a[nx][ny]!=-1)
continue;
r.step=step+1,r.x=nx,r.y=ny;
zheng.push(r);
a[nx][ny]=r.step;
}
}
int k,ans=2e9;
cin>>k;
for(int i=0;i<k;i++)
{
int x,y;
cin>>x>>y;
if(ans!=2e9)continue;
if(a[x-1][y-1]!=-1&&a[x-1][y-1]<=i)
ans=i;
}
if(ans==2e9)
cout<<"NO"<<endl;
else
cout<<"YES "<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
solve();
return 0;
}