CF97D Robot in Basement
CF97D Robot in Basement
题意翻译
在一个n*m(n,m <= 150) 的网格上,有一些格子是障碍的,并且网格边界上的格子均是障碍的,另有一个非障碍的格子是出口。一个机器人可以根据程序在该网格上行走。一段程序是一个由UDLR四种指令组成的字符串,机器人会依次执行每个命令,一个指令会使机器人向指定的方向移动一格,如果对应的格子为障碍则不动,现在给定一格长度为l(l <= 1e5)的程序,求它的一个最短前缀p,使得对于一开始的网格上任意非障碍位置都是机器人,在执行完程序p之后都停在出口上。
题解:
暴力的思路是一个一个按序列模拟。但是很容易发现的性质是各个机器人的行动是互相独立的,不存在谁挡谁路的情况。这样的话,可以在每个空位都放一个机器人,然后大家同步走,直到大家都重合了并且都到终点了,这时就是最少的步数了。
这也就变成了模拟题。
那么很自然地想到了用0/1表示有没有机器人,然后用位运算模拟就行。
模拟的时候大约遵从以下思路:因为bitset没有二维的,所以先考虑把它映射到一维。然后发现机器人一直在左右上下地动,墙是不动的,比较难维护,所以考虑开3个bitset分别记录墙、机器人、出口。最后,上下左右的模拟需要在一维状态下进行,这里需要特殊注意。
代码:
#include<cstdio>
#include<bitset>
using namespace std;
const int maxn=155;
const int maxm=1e5+5;
int n,m,k;
int id[maxn][maxn];
char s[maxm];
bitset<50005> a,b,e,mp;
void init()
{
int tot=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
id[i][j]=tot++;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
init();
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=m;j++)
{
if(s[j]=='#')
mp[id[i][j]]=1;
else
a[id[i][j]]=1;
if(s[j]=='E')
e[id[i][j]]=1;
}
}
scanf("%s",s+1);
b=a;
for(int i=1;i<=k+1;i++)
{
if(a==e)
{
printf("%d\n",i-1);
return 0;
}
if(s[i]=='U')
a=(((a>>m)&b)|((mp<<m)&a));
else if(s[i]=='D')
a=(((a<<m)&b)|((mp>>m)&a));
else if(s[i]=='L')
a=(((a>>1)&b)|((mp<<1)&a));
else
a=(((a<<1)&b)|((mp>>1)&a));
}
puts("-1");
return 0;
}