我们在搜索的时会记录我们走了多少步 b[x][y], 当我们走到终点时,往回找是否b[x][y]=b[xx][yy]+1,满足则(xx,yy)点就是(x,y)的前一个点。
代码:
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=10;
ll maze[maxn][maxn],b[maxn][maxn],vis[maxn][maxn];
ll dx[4]={-1,1,0,0};
ll dy[4]={0,0,-1,1};
struct node{
ll x,y;
};
node que[1000];
queue<node> q;
bool flag=0;
void bfs(ll xx,ll yy)
{
ll ddx,ddy;
node temp;
temp.x=xx;
temp.y=yy;
vis[xx][yy]=1;
q.push(temp);
while(!q.empty())
{
if(flag) break;
else
{
temp=q.front();
q.pop();
xx=temp.x;
yy=temp.y;
if((xx==5&&yy==5))//倒序追踪法
{
flag=1;
ll k=1;
while(!(xx==1&&yy==1))
{
que[k].x=xx;
que[k++].y=yy;
for(int i=0;i<4;i++)//找他前一个点
{
ll rx=xx+dx[i];
ll ry=yy+dy[i];
if(rx<=5&&rx>=0&&ry>=0&&ry<=5&&b[rx][ry]==b[xx][yy]-1)
{
xx=rx;
yy=ry;
break;
}
}
}
que[k].x=1;//起点别忘了
que[k].y=1;
for(int i=k;i>=1;i--)
cout<<"("<<que[i].x-1<<", "<<que[i].y-1<<")"<<endl;
}
else
{
for(int i=0;i<4;i++)
{
ddx=xx+dx[i];
ddy=yy+dy[i];
if(ddx>=0&&ddx<=5&&ddy>=0&&ddy<=5&&vis[ddx][ddy]==0&&maze[ddx][ddy]==0)
{
vis[ddx][ddy]=1;
b[ddx][ddy]=b[xx][yy]+1;
temp.x=ddx,temp.y=ddy;
q.push(temp);
}
}
}
}
}
}
int main()
{
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
cin>>maze[i][j];
bfs(1,1);
//cout<<b[5][5];
return 0;
}
拓展:
如果有多路径,输出字典序最小的一条路径呢?
那我们bfs时候就不能从起点开始搜了,我们从终点开始往起点搜,这样我们再找路径的时候根据题目可以保证每次走的字典序都是最小的。