题目描述:
有一个机器人,他在迷宫中有六种行动方式,用字符表示(用(i,j)代表机器人在迷宫中的位置):
- U: 如果(i-1,j)不是墙, 机器人移动到(i-1,j) . 否则不做任何事;
- D: 如果(i+1,j)不是墙, 机器人移动到(i-1,j) . 否则不做任何事;
- L: 如果(i,j-1)不是墙, 机器人移动到(i-1,j) . 否则不做任何事;
- R: 如果(i,j+1)不是墙, 机器人移动到(i-1,j) . 否则不做任何事;
- P: 如果有垃圾就把它捡起来. 否则不做任何事.
- I: 不做任何事.
题目会给出一个包含'U','D','L','R','P','I'的长度为243的字符串s,机器人的下一个行动会根据s[x+1]所代表的指令来行动,
x=3^4*t(i,j)+3^3*t(i-1,j)+3^2*t(i+1,j)+3*t(i,j+1);
t(i,j)代表在(i,j)位置上如果有什么都没有为0,有墙为1,有垃圾为2,
机器人的初始位置为(a,b),迷宫的为n*m的网格,机器人所要执行指令的次数为k。
现在要求输出机器人所捡垃圾的个数。
分析:
这是一道模拟题,只要做到要求就差不多可以做出来了,首先k是很大的,所以需要判断什么时候可以结束,有三种结束的情况,第一种,当前指令为I,第二种,机器人需要移动但是下一步是墙,无法移动,第三种,机器人进入循环,即一直在一条路线上转圈。前面两种比较好判断,最后一种需要通过映射标记一下当前位置以及下一步指令,但是当机器人捡起了垃圾,之前所有标记都要解除。
代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
const int N=2000+5,dx[]={0,-1,1,0,0},dy[]={0,0,0,-1,1};
string s,buf;
int sz[N][N];
ll zh(int a,int b)
{
return a*1000000+b*10+sz[a][b];
}
map<ll,int>mmp;
map<char,int>mp1;
void init()
{
mp1['P']=-1;
mp1['I']=0;
mp1['U']=1;
mp1['D']=2;
mp1['L']=3;
mp1['R']=4;
}
int zh2(int a,int b)
{
return 81*sz[a][b]+27*sz[a-1][b]+9*sz[a+1][b]+3*sz[a][b-1]+sz[a][b+1];
}
int main()
{
init();
int T;
cin>>T;
while(T--)
{
int ans=0;
int n,m;
int a,b;
ll k;
cin>>n>>m>>a>>b>>k;
cin>>s;
for(int i=1;i<=n;i++)
{
cin>>buf;
for(int j=0;j<m;j++)
{
int x=buf[j]-'0';
sz[i][j+1]=x;
}
}
while(k--)
{
mmp[zh(a,b)]=1;
int na,nb;
int zl=mp1[s[zh2(a,b)]];
if(zl==-1)
{
if(sz[a][b]==2)
{
sz[a][b]=0;ans++;
mmp.clear();
}
na=a;nb=b;
}
else
{
na=a+dx[zl];
nb=b+dy[zl];
if(sz[na][nb]==1)
{
na=a;nb=b;
}
}
if(mmp[zh(na,nb)]==1)
{
break;
}
a=na;
b=nb;
}
printf("%d\n",ans);
mmp.clear();
}
return 0;
}