题目描述
小明置身于一个迷宫,请你帮小明找出从起点到终点的最短路程。
小明只能向上下左右四个方向移动。输入格式
输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是两个整数N和M(1<=N,M<=100)。
接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。
字符的含义如下:
‘S’:起点
‘E’:终点
‘-’:空地,可以通过
‘#’:障碍,无法通过
输入数据保证有且仅有一个起点和终点。输出格式
对于每组输入,输出从起点到终点的最短路程,如果不存在从起点到终点的路,则输出-1。
样例输入
1 5 5 S-### ----- ##--- E#--- ---##样例输出
9
一、A*算法
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#include<unordered_map>
#define x first
#define y second
using namespace std;
const int N=105;
char a[N][N];
int n,m,dist[N][N],sx,sy,ex,ey;
bool st[N][N];
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef pair<int,PIII> PIIII;
int ne[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void Dijkstra()
{memset(st,false,sizeof st);priority_queue<PIII,vector<PIII>,greater<PIII>> heap;heap.push({0,{ex,ey}});memset(dist,0x3f,sizeof dist);dist[ex][ey]=0;while(heap.size()){auto it=heap.top();heap.pop();int xx=it.y.x,yy=it.y.y,distance=it.x;if(st[xx][yy]) continue;st[xx][yy]=true;for(int i=0;i<=3;i++){int tx=xx+ne[i][0],ty=yy+ne[i][1];if(!st[tx][ty]&&tx>=0&&tx<n&&ty>=0&&ty<m&&a[tx][ty]!='#'){if(dist[tx][ty]>distance+1){dist[tx][ty]=distance+1;heap.push({dist[tx][ty],{tx,ty}});}}}}
}
int astar()
{if(dist[sx][sy]==0x3f3f3f3f) return -1;priority_queue<PIIII,vector<PIIII>,greater<PIIII>> heap;heap.push({dist[sx][sy],{0,{sx,sy}}});memset(st,false,sizeof st);while(heap.size()){auto it=heap.top();heap.pop();int distance=it.y.x,xx=it.y.y.x,yy=it.y.y.y;if(xx==ex&&yy==ey) return distance;if(st[xx][yy]) continue;st[xx][yy]=true;for(int i=0;i<=3;i++){int tx=ne[i][0]+xx,ty=yy+ne[i][1];if(a[tx][ty]=='#') continue;if(!st[tx][ty]&&tx>=0&&tx<n&&ty>=0&&ty<m){heap.push({distance+1+dist[tx][ty],{distance+1,{tx,ty}}});}}}return -1;
}
int main()
{int t;cin>>t;while(t--){cin>>n>>m;memset(a,'\0',sizeof a);for(int i=0;i<n;i++)for(int j=0;j<m;j++){cin>>a[i][j];if(a[i][j]=='S') sx=i,sy=j;if(a[i][j]=='E') ex=i,ey=j;}Dijkstra();cout<<astar()<<endl;}
}
二、BFS(DFS省略不写,不是因为我太懒才不想写)
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
using namespace std;
const int N=105;
typedef pair<int,int> PII;
char a[N][N];
int t,n,m,sx,sy,ex,ey;
int dist[N][N];
bool st[N][N];
int ne[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int BFS()
{queue<PII> q;q.push({sx,sy});memset(dist,0x3f,sizeof dist);memset(st,false,sizeof st);dist[sx][sy]=0;st[sx][sy]=true;while(q.size()){auto it=q.front();q.pop();int x=it.first,y=it.second;if(x==ex&&y==ey) return dist[x][y];for(int i=0;i<=3;i++){int tx=x+ne[i][0],ty=y+ne[i][1];if(tx>=0&&tx<n&&ty>=0&&ty<m&&a[tx][ty]!='#'&&!st[tx][ty]){dist[tx][ty]=dist[x][y]+1;q.push({tx,ty});st[tx][ty]=true;}}}return -1;
}
int main()
{cin>>t;while(t--){cin>>n>>m;memset(a,'\0',sizeof a);for(int i=0;i<n;i++)for(int j=0;j<m;j++){cin>>a[i][j];if(a[i][j]=='S')sx=i,sy=j;if(a[i][j]=='E')ex=i,ey=j;}cout<<BFS()<<endl;}}
三、双向广搜
#include<iostream>
#include<queue>
#include<cstring>
#include<unordered_map>
using namespace std;
const int N=105;
typedef pair<int,int> PII;
int da[N][N],db[N][N],n,m,t,sx,sy,ex,ey;
char a[N][N];
int ne[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int extend(queue<PII> &q,int da[][N],int db[][N])
{auto it=q.front();q.pop();int x=it.first,y=it.second;for(int i=0;i<=3;i++){int tx=x+ne[i][0],ty=y+ne[i][1];if(tx>=0&&tx<n&&ty>=0&&ty<m&&a[tx][ty]!='#'&&da[tx][ty]==-1){if(db[tx][ty]!=-1) return da[x][y]+db[tx][ty]+1;da[tx][ty]=da[x][y]+1;q.push({tx,ty});}}return -1;
}
int BFS()
{queue<PII> qa,qb;qa.push({sx,sy});qb.push({ex,ey});memset(da,-1,sizeof da);memset(db,-1,sizeof db);da[sx][sy]=0;db[ex][ey]=0;while(qa.size()&&qb.size()){int t;if(qa.size()<=qb.size()) t=extend(qa,da,db);else t=extend(qb,db,da);if(t!=-1) return t;}return -1;
}
int main()
{cin>>t;while(t--){cin>>n>>m;memset(a,'\0',sizeof a);for(int i=0;i<n;i++)for(int j=0;j<m;j++){cin>>a[i][j];if(a[i][j]=='S') sx=i,sy=j;if(a[i][j]=='E') ex=i,ey=j;}cout<<BFS()<<endl;}
}