给出一个N*M的地图,现在最多有26个人,分别用26个字母表示分落在地图各处,#代表墙,现在有q个操作,表示让每个人按照没一轮次都按照要求方向走len步,问哪几个人可以将所有操作都走完的过程中,不会撞墙。
思路:
显然按照Bfs去模拟的话,会TLE。我们考虑问题的特点。
我们知道,每一次操作都是按照一个方向去走的,我们要判定的问题只有是否撞墙这一个点。
那么我们不妨预处理出4个前缀和,N【i】【j】表示在(i,j)这个点上,往北走多少步之内不会撞墙。
其他3个方向同理即可。
那么我们只需要O(26*q)去模拟判定即可。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
char a[1500][1500];
int N[1500][1500];
int S[1500][1500];
int E[1500][1500];
int W[1500][1500];
char op[150000][3];
int move[150000];
int q,ok,n,m;
int Slove(int x,int y)
{
for(int i=1;i<=q;i++)
{
if(op[i][0]=='N')
{
if(N[x][y]-move[i]>=0)
{
x-=move[i];
}
else return 0;
}
if(op[i][0]=='S')
{
if(S[x][y]-move[i]>=0)
{
x+=move[i];
}
else return 0;
}
if(op[i][0]=='W')
{
if(W[x][y]-move[i]>=0)
{
y-=move[i];
}
else return 0;
}
if(op[i][0]=='E')//dong
{
if(E[x][y]-move[i]>=0)
{
y+=move[i];
}
else return 0;
}
}
ok=1;
return 1;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
ok=0;
for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(a[j][i]=='#')N[j][i]=0;
else N[j][i]=N[j-1][i]+1;
}
for(int j=n;j>=1;j--)
{
if(a[j][i]=='#')S[j][i]=0;
else S[j][i]=S[j+1][i]+1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]=='#')W[i][j]=0;
else W[i][j]=W[i][j-1]+1;
}
for(int j=m;j>=1;j--)
{
if(a[i][j]=='#')E[i][j]=0;
else E[i][j]=E[i][j+1]+1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
N[i][j]--;
S[i][j]--;
W[i][j]--;
E[i][j]--;
}
}
scanf("%d",&q);
for(int i=1;i<=q;i++)scanf("%s%d",op[i],&move[i]);
for(int z=1;z<=26;z++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]-'A'+1==z)
{
int tmp= Slove(i,j);
if(tmp==1)printf("%c",a[i][j]);
}
}
}
}
if(ok==0)printf("no solution\n");
printf("\n");
}
}