题目链接http://poj.org/problem?id=3984
Bfs + vis记录路径
对图进行BFS能得到最短路的原因:
- BFS肯定能到达 所有能从起点出发到达的点(想象一下从起点开始的“洪泛”效应)
- BFS每到达一个点,都是从起点到该点的最短路径(找个图模拟一下即可发现)
综合1,2点可知:从起点开始使用BFS能得到到终点的最短路径。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
int go[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int map[5][5];
int vis[5][5];
typedef struct node
{
int x,y;
}Node;
Node e;
queue<Node> q;
void Bfs(Node s)
{
q.push(s);
while(!q.empty()){
Node cur=q.front();
q.pop();
if(cur.x==e.x&&cur.y==e.y)
return ;
for(int i=1;i<=4;i++){ //方向i不能为0
int x=cur.x+go[i-1][0];
int y=cur.y+go[i-1][1];
if(x>=0&&x<5&&y>=0&&y<5&&!map[x][y]&&!vis[x][y]){
vis[x][y]=i;//没访问过才置于访问状态,并标记方向,换句话说,每个点只会被标记一次方向,而且是最先到达这个点的那一个方向,
//而且因为配合Bfs,这个方向所指向的路径就是到达这个点的最短路径,所以这个点的vis不需要被更新,
//之后到达这个点的路径肯定要更长,就可以直接跳过,所以这里可以用vis同时实现记录访问状态和路径信息的作用
Node tmp;
tmp.x=x; tmp.y=y;
q.push(tmp);
}
}
}
}
void print(int x,int y) //函数的涵义:输出以该结点结尾的路径
{ //原问题可以划分成 输出以该结点的前驱结点结尾的路径(规模更小的子问题)+ 输出该结点本身
int prex,prey;
if(vis[x][y]!=-1){
prex=x-go[vis[x][y]-1][0];
prey=y-go[vis[x][y]-1][1];
print(prex,prey);
}
printf("(%d, %d)\n",x,y);
}
int main()
{
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
cin>>map[i][j];
memset(vis,0,sizeof vis);
e.x=4; e.y=4;
Node s;
s.x=0; s.y=0;
vis[s.x][s.y]=-1;//起点vis不能为0,因为起点要置于访问状态,且不能和所有方向i相同
Bfs(s);
print(e.x,e.y);
return 0;
}