题解:P11864 「o.OI R1」α+β Problem

题目传送门

思路

首先墙就是个虚设,因为它除了挡住路外一点作用都没有,所以根本就不需要放墙。

我们先贪心地去假设除起始位置外,其他位置都放置箱子。然后模拟机器人行走的过程,并用两个数组分别记录箱子是否被移动或删除。

  • 当指令为 A 时,左转;
  • 当指令为 D 时,右转;
  • 当指令为 W 时,分类讨论一下,
    1. 如果前方无箱子,直接向前移动;
    2. 如果前方有箱子,且前方的前方超出边界,则删除该箱子后前进;
    3. 如果前方有箱子,且前方的前方无箱子,则将箱子推到前方的前方,标记其已被推动,再前进;
    4. 如果前方有箱子,且前方的前方有箱子,则将前方的前方的箱子删除,然后进行第 3 步的操作;
  • 当指令为 S 时,删除后方的箱子(如果有的话),再后退一格。

如果箱子没被删除且有被移动过,则在输出答案时在其原位上输出它。

代码

#include <bits/stdc++.h>
using namespace std;

const int N=2003,K=1e6+6;

int t,n,m,sx,sy,k,g[N][N];
int d[4][2]={{-1,0},{0,1},{1,0},{0,-1}};//上下左右依次存在d中
bool val[N*N],del[N*N];//val存是否被移动过,del存是否被删除,注意数组大小
char s[K];

int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d%d%s",&n,&m,&sx,&sy,&k,s+1);
        for(int i=1,cnt=0;i<=n;i++)
            for(int j=1;j<=m;j++)
                g[i][j]=++cnt,val[g[i][j]]=del[g[i][j]]=0;
        //从上到下,从左到右,从1开始给每一个格子上的箱子编号,方便统计
        int x=sx,y=sy,p=0;//x,y存机器人现在的坐标,p存方向
        del[g[x][y]]=1,g[x][y]=0;//删除起点上的箱子
        for(int i=1;i<=k;i++){
            if(s[i]=='A')
                p=(p+3)%4;//左转
            else if(s[i]=='D')
                p=(p+1)%4;
            else if(s[i]=='W'){
                int xx=x+d[p][0],yy=y+d[p][1];
                if(g[xx][yy]){
                    int xxx=xx+d[p][0],yyy=yy+d[p][1];
                    if(0<xxx && xxx<=n && 0<yyy && yyy<=m)
                        del[g[xxx][yyy]]=1,g[xxx][yyy]=g[xx][yy],val[g[xx][yy]]=1;
                    else
                        del[g[xx][yy]]=1;
                    //前方的前方有箱子(无箱子就是0,不影响统计)删,挪动前方的箱子,标记为移动过
                    //越界直接删
                    g[xx][yy]=0;
                }
                x=xx,y=yy;
            }else if(s[i]=='S'){
                int xx=x+d[(p+2)%4][0],yy=y+d[(p+2)%4][1];
                if(g[xx][yy])
                    del[g[xx][yy]]=1,g[xx][yy]=0;
                x=xx,y=yy;
                //后退,有箱子删
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(i==sx && j==sy)
                    printf("X");//起点要特判
                else
                    printf("%c",val[(i-1)*m+j] && !del[(i-1)*m+j]? 'S':'.');
                //如果被原本在该位置的箱子移动过且未被删除则在该格放置箱子
            }
            puts(""); 
        }
    }
    return 0;
}

有问题欢迎留言。

posted @ 2025-07-14 10:39  andycode  阅读(13)  评论(0)    收藏  举报