题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4092
题意:
给你一个n*m(n*m<=2000)的数字矩阵t,每个数字均为0,1,2其中之一.保证边界都是1
0表示该格子空
1表示该格子有墙
2表示该格子有一个垃圾
一个机器人从点(x,y)出发,最多进行k(k<=1e18)次操作。
给你一个长度为243的操作序列s,由字母UDLRPI构成。
当机器人位于当前位置(i,j),执行一次操作:
计算pos=81*t[i][j]+27*t[i-1][j]+9*t[i+1][j]+3*t[i][j-1]+t[i][j+1]
查询s[pos],获得字符ch,
ch='P':如果当前格子有垃圾,则捡起来,否则不动
ch='U':如果t[i-1][j]!=1,则移动过去,否则不动
ch='D':如果t[i+1][j]!=1,则移动过去,否则不动
ch='L':如果t[i][j-1]!=1,则移动过去,否则不动
ch='R':如果t[i][j+1]!=1,则移动过去,否则不动
ch='I':不动
求k步后捡到多少垃圾。
思路:直接模拟,注意到每个格子最多经过两次,所以min(n*m*n*m,k)步之后一定会停在某个地方或者无垃圾格子的循环中。
注意遇到墙就直接停。(比赛的时候死活以为最多n*m步,唉,智商下线了)
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
const int maxn=2010;
int n,m,A,B;
ll K;
int a[maxn],tt[maxn][maxn],sta,pos;
int ans;
char s[maxn][maxn];
char ss[maxn];
int fg;
int cal(int i,int j)
{
return 81*tt[i][j]+27*tt[i-1][j]+9*tt[i+1][j]+3*tt[i][j-1]+tt[i][j+1];
}
int ok[maxn][maxn];
void bfs()
{
ans=0;
ll t=1;
int num=0;
int x=A,y=B;
while(t<=K)
{
t++;
if(tt[x][y]==1) break;
int pos=cal(x,y);
if(ss[pos]=='I') continue;
else if(ss[pos]=='P')
{
if(tt[x][y]==2)
{
tt[x][y]=0;
num++;
}
}
else if(ss[pos]=='U') x--;
else if(ss[pos]=='D') x++;
else if(ss[pos]=='L') y--;
else if(ss[pos]=='R') y++;
}
ans=num;
}
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
scanf("%d%d%lld",&A,&B,&K);
scanf("%s",ss);
rep(i,1,n)
scanf("%s",s[i]+1);
memset(tt,0,sizeof(tt));
rep(i,1,n)
rep(j,1,m)
tt[i][j]=(s[i][j]&15);
K=min(K,((ll)n*(ll)n*(ll)m*(ll)m));
bfs();
printf("%d\n",ans);
//if(fg) puts("Yes"); else puts("No");
}
return 0;
}