题解:P12684 【MX-J15-T4】叉叉学习魔法
不一样的做法。
发现不能带
记一个节点的状态为
代码非常好写。
#include<bits/stdc++.h>
using namespace std;
constexpr int X=5005, inf=0x3f3f3f3f;
constexpr int dx[9]={0,-1,-1,1,1,-1,0,0,1};
constexpr int dy[9]={0,-1,1,-1,1,0,-1,1,0};
int N,M,dis[X][X],mn[X][X];
bool vis[X][X],mp[X][X];
pair<int,int> S,T;
queue<pair<int,int>> q1,q2;
inline pair<int,int> get_min()
{
pair<int,int> res(inf,inf);
if(q1.empty()){
res=q2.front(); q2.pop();
}
else if(q2.empty()){
res=q1.front(); q1.pop();
}
else{
pair<int,int> C1=q1.front();
pair<int,int> C2=q2.front();
if(dis[C1.first][C1.second]>dis[C2.first][C2.second]){
res=C2, q2.pop();
}
else if(dis[C1.first][C1.second]<dis[C2.first][C2.second]){
res=C1, q1.pop();
}
else{
if(mn[C1.first][C1.second]<mn[C2.first][C2.second]){
res=C1, q1.pop();
}
else{
res=C2, q2.pop();
}
}
}
return res;
}
void BFS()
{
memset(dis,0x3f,sizeof dis);
memset(mn,0x3f,sizeof mn);
q1.emplace(S);
dis[S.first][S.second]=mn[S.first][S.second]=0;
while(!q1.empty()||!q2.empty()){
auto C=get_min();
int x=C.first, y=C.second;
if(vis[x][y]) continue;
vis[x][y]=1;
for(int i=1;i<=4;i++){
int nx=x+dx[i], ny=y+dy[i];
if(vis[nx][ny]) continue;
if(mp[nx][ny]) continue;
if(nx<1||nx>N||ny<1||ny>M) continue;
if(dis[nx][ny]<dis[x][y]) continue;
if(dis[nx][ny]==dis[x][y]&&mn[nx][ny]<=mn[x][y]+1) continue;
dis[nx][ny]=dis[x][y];
mn[nx][ny]=mn[x][y]+1;
q1.emplace(nx,ny);
}
for(int i=5;i<=8;i++){
int nx=x+dx[i], ny=y+dy[i];
if(vis[nx][ny]) continue;
if(mp[nx][ny]) continue;
if(nx<1||nx>N||ny<1||ny>M) continue;
if(dis[nx][ny]<dis[x][y]+1) continue;
if(dis[nx][ny]==dis[x][y]+1&&mn[nx][ny]<=mn[x][y]) continue;
dis[nx][ny]=dis[x][y]+1;
mn[nx][ny]=mn[x][y];
q2.emplace(nx,ny);
}
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>N>>M;
for(int i=1;i<=N;i++){
string s; cin>>s;
for(int j=1;j<=M;j++){
if(s[j-1]=='#') mp[i][j]=1;
if(s[j-1]=='X') S={i,j};
if(s[j-1]=='W') T={i,j};
}
}
BFS();
if(dis[T.first][T.second]==0x3f3f3f3f){
cout<<-1<<' '<<-1;
}
else{
cout<<dis[T.first][T.second]<<' '<<mn[T.first][T.second];
}
}