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;
}
posted @ 2020-11-30 19:48  Seaway-Fu  阅读(79)  评论(0编辑  收藏  举报