[GDOI22pj2D] 机器人
第四题 机器人
提交文件: robot.cpp
输入文件: robot.in
输出文件: robot.out
时间空间限制: 3 秒, 512 MB
刚上初一的小纯特别喜欢机器人,这周末,她报名了学校的“小机器人俱乐部”,而进入俱乐部需要通过一场考试。
考试场地可以看作一个$ n × m$ 的网格图,行从上往下标号为 \(1, · · · , n\),列从左往右标号为 \(1, · · · , m\)。每个格子有三种可能:空地,障碍物,机器人(有且只有一个),分别用“.”、“*”、“R”表示。现在小纯需要控制机器人在考试场地上行走,她每秒可以发送一条指令,为“W”——往上走、“S”——往下走、“A”——往左走、“D”——往右走的其中之一。由于俱乐部的机器人是避障机器人,当机器人接收到一条指令的时候,如果即将到达的位置为障碍物,那么机器人将留在原地,否则机器人向对应方向走一步。如果其走出边界则考试失败(例如在第一行发送指令向上走)。
为了增加考试的难度,俱乐部提供的机器人的信号接收器都存在问题。换言之,对于小纯给出的每一条指令,机器人有可能接收到指令并执行,也有可能接收不到指令并保持不动.
现在小纯提供了一个指令序列,她想知道,这个指令序列是否存在某些情况使得这个指令序列走出边界。
输入格式
每个测试点包含多组数据。
第一行一个正整数 T,表示数据组数。
对于每组数据:
第一行一个由“W,S,A,D”组成的字符串 S,表示小纯的指令序列。
第二行两个正整数 n, m 表示考试场地的长度和宽度。
接下来 n 行,每行一个长度为 m 的字符串,描述考试场地。
输出格式
对于每组数据,输出一行。“YES”表示可能走出考试场地,“NO”表示不可能走出场地。(不包含引号)
样例数据
2
DWAWAADWASDSWSS
8 8
.***...*
**....*.
**...**.
**.*.***
......**
.*..*..*
*...**R*
...*..**
DWAWAADWASDSWSS
8 8
.***...*
**....*.
**...**.
**.*.***
......**
.*..*..*
*...**R*
..**..**
YES
NO
数据范围
令 |S| 表示指令序列长度。对于所有测试点,\(1 ≤ T ≤ 10,1 ≤ |S| ≤ 10^5,1 ≤ n, m ≤ 500\)。
测试点 | $|S| ≤ $ | \(n, m ≤\) |
---|---|---|
1 ∼ 4 | \(15\) | 10 |
5 ∼ 6 | $ 50$ | 50 |
7 ∼ 10 | \(1000\) | 50 |
11 ∼ 14 | \(10^5\) | 70 |
15 ∼ 20 | $ 10^5$ | 500 |
首先我们尝试按照运行到了哪条指令来看,到了那条指令后,所有之前到过的点都可以往指令指的方向走一步(如果没有障碍物的话)。解释一下,因为之前到过的点都可以一直留在那里,等到这个指令再走。因此也可以发现,如果一个地方之前到过,那就没有必要再走了。但这样复杂度还是很大。
我们还可以发现,一个之前往上走过的店,第二次就不用再往上走了,因为那个点肯定到过了。所以我们开四个队列存储还没有往上下左右走过的店,每次到了一个新的点,那就给他在四个队列里都装上。这样可以达到\(O(|s|+n^2)\)的复杂度。如果一走出去那就输出"YES"。
#include<cstdio>
#include<cstring>
const int N=505,M=1e5+5,dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
struct node{
int x,y;
}q[N*N][4];//0上1下2左3右
int v[N][N],t,n,m,len,x,y,f,l[4],r[4],k,l1,r1;
char s[M],mp[N];
int notok(int x,int y)
{
return x<1||x>n||y<1||y>m;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%s%d%d",s+1,&n,&m);
len=strlen(s+1);
memset(v,f=0,sizeof(v));
for(int i=1;i<=n;i++)
{
scanf("%s",mp+1);
for(int j=1;j<=m;j++)
{
if(mp[j]=='*')
v[i][j]=1;
if(mp[j]=='R')
x=i,y=j;
}
}
q[l[0]=r[0]=1][0]=q[l[1]=r[1]=1][1]=q[l[2]=r[2]=1][2]=q[l[3]=r[3]=1][3]=(node){x,y};
for(int i=1;i<=len;i++)
{
if(s[i]=='W')
k=0;
else if(s[i]=='S')
k=1;
else if(s[i]=='A')
k=2;
else
k=3;
l1=l[k],r1=r[k],l[k]=r[k]+1;
for(int j=l1;j<=r1;j++)
{
x=q[j][k].x+dx[k],y=q[j][k].y+dy[k];
if(!v[x][y])
{
if(notok(x,y))
{
f=1;
break;
}
q[++r[1]][1]=q[++r[2]][2]=q[++r[3]][3]=q[++r[0]][0]=(node){x,y},v[x][y]=1;
}
}
if(f)
break;
}
if(f)
printf("YES\n");
else
printf("NO\n");
}
}