两种方法思路:将门设置为不可通过,然后计算从起点到终点的直接路径;计算起点到钥匙+钥匙到门+门到终点的路径之和,比较他们两个哪一个更小,如果比较结果等于0x3f3f3f3f的话,说明终点被墙围住了,不可能到达。
两个计算模拟了尝试直接到达终点,以及拿钥匙再到终点的这两个过程。如果门挡住去路,那么最短路一定是拿钥匙再到终点的路径,如果门不能挡住去路,那么最短路是两者最小值。如果钥匙拿不到并且门也挡住了去路,那么显然是死局。
两种方法,第一种是dijksra算法求最短路
#include<bits/stdc++.h>
using namespace std;
int h,w;
const int M=505;
char mp[M][M];
bool vis[M][M];
int sx,sy,ex,ey,dx,dy,kx,ky;
bool flag;
struct node{
int x,y;
node(int a,int b){x=a; y=b;}
node(){}
};
int mov[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
bool check(int x,int y){
return x>=1&&x<=h&&y>=1&&y<=w;
}
int key;
int dis[M][M];
int bfs(int px,int py,int tx,int ty){
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<node> q;
vis[px][py]=true;
q.push(node(px,py));
dis[px][py]=0;
while(!q.empty()){
node tmp=q.front();
q.pop();
for(int i=0;i<4;i++){
int xx=tmp.x+mov[i][0];
int yy=tmp.y+mov[i][1];
if(xx==tx&&yy==ty) return dis[tmp.x][tmp.y]+1;
if(check(xx,yy)&&!vis[xx][yy]&&mp[xx][yy]!='W'&&mp[xx][yy]!='D'){
if(dis[xx][yy]>=dis[tmp.x][tmp.y]+1){
dis[xx][yy]=dis[tmp.x][tmp.y]+1;
// cout<<dis[xx][yy]<<" ";
vis[xx][yy]=true;
q.push(node(xx,yy));
}
}
}
}
return 0x3f3f3f3f;
}
int main(){
cin>>h>>w;
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++){
cin>>mp[i][j];
if(mp[i][j]=='S'){
sx=i; sy=j;
}
if(mp[i][j]=='E'){
ex=i; ey=j;
}
if(mp[i][j]=='D'){
dx=i; dy=j;
}
if(mp[i][j]=='K'){
kx=i; ky=j;
}
}
int dis1=bfs(sx,sy,ex,ey);
int dis2=bfs(sx,sy,kx,ky);
if(dis2!=0x3f3f3f3f){
dis1=min(dis1,dis2+bfs(kx,ky,dx,dy)+bfs(dx,dy,ex,ey));
}
if(dis1==0x3f3f3f3f) cout<<"-1"<<'\n';
else cout<<dis1<<'\n';
int ans=0;
}
第二种是根据bfs先到达终点的路径一定最短的原理
#include<bits/stdc++.h>
using namespace std;
int h,w;
const int M=505;
char mp[M][M];
bool vis[M][M];
int sx,sy,ex,ey,dx,dy,kx,ky;
bool flag;
struct node{
int x,y,step;
node(int a,int b,int c){x=a; y=b;step=c;}
node(){}
};
int mov[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
queue<node> q;
bool check(int x,int y){
return x>=1&&x<=h&&y>=1&&y<=w;
}
int key;
int bfs(int px,int py,int tx,int ty){
memset(vis,0,sizeof(vis));
while(!q.empty()){
q.pop();
}
vis[px][py]=true;
q.push(node(px,py,0));
dis[px][py]=0;
while(!q.empty()){
node tmp=q.front();
q.pop();
for(int i=0;i<4;i++){
int xx=tmp.x+mov[i][0];
int yy=tmp.y+mov[i][1];
if(xx==tx&&yy==ty) {
// cout<<tmp.step+1<<" ";
// cout<<endl;
return tmp.step+1;
}
if(check(xx,yy)&&!vis[xx][yy]&&mp[xx][yy]!='W'&&mp[xx][yy]!='D'){
vis[xx][yy]=true;
q.push(node(xx,yy,tmp.step+1));
}
}
}
// cout<<endl;
return 0x3f3f3f3f;
}
int main(){
cin>>h>>w;
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++){
cin>>mp[i][j];
if(mp[i][j]=='S'){
sx=i; sy=j;
}
if(mp[i][j]=='E'){
ex=i; ey=j;
}
if(mp[i][j]=='D'){
dx=i; dy=j;
}
if(mp[i][j]=='K'){
kx=i; ky=j;
}
}
int dis1=bfs(sx,sy,ex,ey);
int dis2=bfs(sx,sy,kx,ky);
if(dis2!=0x3f3f3f3f){
dis1=min(dis1,dis2+bfs(kx,ky,dx,dy)+bfs(dx,dy,ex,ey));
}
if(dis1==0x3f3f3f3f) cout<<"-1"<<'\n';
else cout<<dis1<<'\n';
int ans=0;
}