此题有个巨大的吐槽的地方就是最终状态的判定有两种情况,相遇或者到一个格子里,不要忘记当队列为空要判定状态为结束。还有可以用方向来代表数组的下标,是代码更具有可读性。
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
int const maxn = 50;
char map[maxn][maxn];
int vis[maxn][maxn][maxn][maxn];
int r,c;
int dr1[] = {-1,1,0,0};
int dc1[] = {0,0,-1,1};
char dre[6];
int dr2[4],dc2[4];
struct point {
int r1,c1,r2,c2;
int val;
point (int aa=0,int bb=0,int aaa=0,int bbb=0,int cc=0):r1(aa),c1(bb),r2(aaa),c2(bbb),val(cc){}
}p1;
bool isin(const point& tmp) {
return tmp.r1>0&&tmp.r1<=r&&tmp.r2>0&&tmp.r2<=r&&tmp.c1>0&&tmp.c1<=c&&tmp.c2>0&&tmp.c2<=c;
}
bool isend(const point& tmp) {
return tmp.r1==tmp.r2&&tmp.c1==tmp.c2;
}
void f() {
for (int i=0;i<4;i++) {
if(dre[i]=='N') {
dr2[i]=-1;
dc2[i]=0;
}
if (dre[i]=='S') {
dr2[i]=1;
dc2[i]=0;
}
if (dre[i]=='W') {
dr2[i]=0;
dc2[i]=-1;
}
if (dre[i]=='E') {
dr2[i]=0;
dc2[i]=1;
}
}
}
int bfs() {
queue<point> Q;
Q.push(p1);
while(!Q.empty()) {
point tmp = Q.front();
Q.pop();
if(tmp.val>=256) return -1;
for (int i=0;i<4;i++) {
int nr1=tmp.r1+dr1[i];
int nc1=tmp.c1+dc1[i];
int nr2=tmp.r2+dr2[i];
int nc2=tmp.c2+dc2[i];
if (map[nr2][nc2]=='#') {
nr2 = tmp.r2;
nc2 = tmp.c2;
}
point pp(nr1,nc1,nr2,nc2,tmp.val+1);
if(isin(pp)&&map[nr1][nc1]=='.'&&map[nr2][nc2]!='!'&&!vis[nr1][nc1][nr2][nc2]) {
if((nr1==nr2&&nc1==nc2)||(nr1==tmp.r2&&nr2==tmp.r1&&nc1==tmp.c2&&nc2==tmp.c1)) return tmp.val+1;
vis[nr1][nc1][nr2][nc2]=1;
Q.push(point(nr1,nc1,nr2,nc2,tmp.val+1));
}
}
}
return -1;
}
int main() {
while(cin>>r>>c) {
memset(vis,0,sizeof(vis));
for (int i=1;i<=r;i++)
for (int j=1;j<=c;j++) {
cin>>map[i][j];
if(map[i][j]=='P') {
p1.r1=i; p1.c1=j;
map[i][j]='.';
}
if (map[i][j]=='H') {
p1.r2=i; p1.c2=j;
map[i][j]='.';
}
}
vis[p1.r1][p1.c1][p1.r2][p1.c2]=1;
cin>>dre;
f();
int ans = bfs();
if(ans!=-1) cout<<ans<<endl;
else cout<<"Impossible"<<endl;
}
}
//方向容易编码错误,题意的理解也容易发生错误。