题目描述
最近吃鸡游戏非常火,你们wyh学长也在玩这款游戏,这款游戏有一个非常重要的过程,就是要跑到安全区内,否则就会中毒持续消耗血量,我们这个问题简化如下
假设地图为n*n的一个图,图中有且仅有一块X的联通快代表安全区域,有一个起点S代表缩圈的时候的起点,图中C代表的是车(保证车的数量小于等于100),标记为.的代表空地,可以任意通过,O代表障碍物不能通过。每次没有车的时候2s可以走一个格(只能走自己的上下左右4个方向),有车的话时间为1s走一个格
现在告诉你最多能坚持的时间为t秒,问你在t秒内(含t秒)能否从s点到达安全区域,能的话输出YES,并且输出最短时间,不能的话输出NO
输入描述:
输入第一行一个整数T(1<=T<=10) 接下来有T组测试数据,每组测试数据输入2个数n和k(1<=n<=100,1<=k<=10^9) 接下来n行,每行n个字符,代表对应的n*n的地图,每个字符都是上面的一种,并且保证只有一个起点,只有一块安全区域。
输出描述:
对于每组测试数据,先输出能否到达,能的话输出YES,然后换行输出最短时间,如果不能的话直接输出NO
示例1
输入
3 2 3 .X S. 2 3 .X SC 2 4 .X S.
输出
NO YES 3 YES 4
思路:X可能不止一个可能是一个连通块,可以用最短路来写。
代码:
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
#define ll long long
const int N=1000+10;
char s[N][N];
int dis[N][N][2];
int vis[N][N][2];
struct node
{
int x,y,z;
};
int m,n,z;
int x[N*N],y[N*N];
bool check(int a,int b)
{
if(a<0||a>=n||b<0||b>=n||s[a][b]=='O')return true;
return false;
}
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int sx,sy;
int main()
{
int T;
cin>>T;
while(T--)
{
scanf("%d%d",&n,&m);
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
scanf("%s",s[i]);
z=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(s[i][j]=='S')sx=i,sy=j;
if(s[i][j]=='X')x[z]=i,y[z++]=j;
dis[i][j][0]=dis[i][j][1]=inf;
}
}
queue<node>Q;
node p,q;
p.x=sx;
p.y=sy;
p.z=0;
dis[sx][sy][0]=0;
vis[sx][sy][0]=1;
Q.push(p);
while(!Q.empty())
{
q=Q.front();
Q.pop();
vis[q.x][q.y][q.z]=0;
for(int i=0;i<4;i++)
{
p.x=q.x+dir[i][0];
p.y=q.y+dir[i][1];
p.z=q.z;
if(check(p.x,p.y))continue;
if(s[p.x][p.y]=='C')p.z=1;
int c;
if(q.z==0)c=2;
else c=1;
if(dis[q.x][q.y][q.z]+c<dis[p.x][p.y][p.z])
{
dis[p.x][p.y][p.z]=dis[q.x][q.y][q.z]+c;
if(vis[p.x][p.y][p.z]==0)
{
vis[p.x][p.y][p.z]=1;
Q.push(p);
}
}
}
}
int ans=inf;
for(int i=0;i<z;i++)
{
ans=min(ans,dis[x[i]][y[i]][0]);
ans=min(ans,dis[x[i]][y[i]][1]);
}
if(ans<=m){
printf("YES\n");
printf("%d\n", ans);
}
else printf("NO\n");
}
return 0;
}