题解:P11864 「o.OI R1」α+β Problem
思路
首先墙就是个虚设,因为它除了挡住路外一点作用都没有,所以根本就不需要放墙。
我们先贪心地去假设除起始位置外,其他位置都放置箱子。然后模拟机器人行走的过程,并用两个数组分别记录箱子是否被移动或删除。
- 当指令为
A时,左转; - 当指令为
D时,右转; - 当指令为
W时,分类讨论一下,- 如果前方无箱子,直接向前移动;
- 如果前方有箱子,且前方的前方超出边界,则删除该箱子后前进;
- 如果前方有箱子,且前方的前方无箱子,则将箱子推到前方的前方,标记其已被推动,再前进;
- 如果前方有箱子,且前方的前方有箱子,则将前方的前方的箱子删除,然后进行第 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;
}
有问题欢迎留言。

浙公网安备 33010602011771号