CF106D 题解
题目传送门
思路
本题可以在前缀和的优化下模拟通过。由于每一次只会在直线上走,我们只需要预处理每一行和每一列可以走的路长。在模拟期间,就可以使用前缀和判断其路程中是否全是可以走的。
AC CODE
#include<bits/stdc++.h>
using namespace std;
int read(){int x=0;char f=1,ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int N=1e3+10,M=1e5+10;
struct node{
int x,y;
};vector<node>vc;
int n,m,r[N][N],c[N][N],op[M],len[M],
dx[]={0,-1,1,0,0},dy[]={0,0,0,-1,1};
char s[N][N];
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i)
scanf("%s",s[i]+1);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(s[i][j]>='A'&&s[i][j]<='Z')
vc.push_back({i,j});
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
r[i][j]=r[i][j-1]+(s[i][j]!='#');
c[i][j]=c[i-1][j]+(s[i][j]!='#');
}
int T=read();
for(int i=1;i<=T;++i){
char ch[1];
scanf("%s",ch);
len[i]=read();
if(ch[0]=='N')
op[i]=1;
else if(ch[0]=='S')
op[i]=2;
else if(ch[0]=='W')
op[i]=3;
else op[i]=4;
}
string ans="";
for(auto it:vc){
int bx=it.x,by=it.y;
int x=it.x,y=it.y;
bool flag=true;
for(int i=1;i<=T;++i){
int xx=x+dx[op[i]]*len[i];
int yy=y+dy[op[i]]*len[i];
if(xx<=0||xx>n||yy<=0||yy>m){
flag=false;
break;
}
int min_x=min(x,xx),min_y=min(y,yy);
int max_x=max(x,xx),max_y=max(y,yy);
if(op[i]>=3){
if(r[max_x][max_y]-r[min_x][min_y-1]!=len[i]+1)
flag=false;
}
else if(c[max_x][max_y]-c[min_x-1][min_y]!=len[i]+1)
flag=false;
if(!flag)
break;
x=xx,y=yy;
}
if(flag)
ans+=s[bx][by];
}
if(ans.empty())
cout<<"no solution\n";
else{
sort(ans.begin(),ans.end());
cout<<ans<<"\n";
}
return 0;
}