题目:
东东有一张地图,想通过地图找到妹纸。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹纸,这两个位置保证为0。既然已经知道了地图,那么东东找到妹纸就不难了,请你编一个程序,写出东东找到妹纸的最短路线。
Input:
输入是一个5 × 5的二维数组,仅由0、1两数字组成,表示法阵地图。
Output:
输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示。数据保证有唯一解。
Sample Input:
0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
0 1 0 1 0
Sample Output:
(0, 0)
(1, 0)
(2, 0)
(3, 0)
(3, 1)
(3, 2)
(2, 2)
(1, 2)
(0, 2)
(0, 3)
(0, 4)
(1, 4)
(2, 4)
(3, 4)
(4, 4)
Hint:
坐标(x, y)表示第x行第y列,行、列的编号从0开始,且以左上角为原点。另外注意,输出中分隔坐标的逗号后面应当有一个空格。
思路:
该问题即是在一个平面直角坐标系中找到一条由原点(0,0)走到终点(5,5)的路径。
将一个点用结构体point表示,dx,dy两个常量数组表示向上、下、左、右四个方向移动,使用bfs方法,创建一个队列que,当que不为空时,取出队首元素,判断是否到达终点,如果到达则准备输出,如果没有则将该点周围可到达的点压入que中,并根据该点坐标在vis数组中打上标记,标记值为上一点在vis中的标记值加一,如此执行直到到达终点。输出时,由终点开始在vis数组中向回寻找可行路径,再逆序输出,便可得到由起点到终点的路径。
代码:
#include <iostream>
#include <queue>
#include <string.h>
#include <vector>
using namespace std;
struct point
{
int x,y;
point()
{
}
point(int a,int b)
{
x=a;
y=b;
}
};
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int vis[5][5];//标记最小到达需要几步
void bfs(int maze[5][5])
{
memset(vis,-1,sizeof(vis));
queue<point> que;
que.push(point(0,0));
vis[0][0]=0;
while(!que.empty())
{
point p=que.front();
que.pop();
if(p.x==4&&p.y==4)
break;
for(int i=0;i<4;i++)
{
int x=p.x+dx[i];
int y=p.y+dy[i];
if(0<=x&&x<=4&&0<=y&&y<=4&&maze[x][y]!=1&&vis[x][y]==-1)
{
vis[x][y]=vis[p.x][p.y]+1;
que.push(point(x,y));
}
}
}
}
void print()
{
vector<point> v;
point now(4,4);
v.push_back(point(4,4));
while(1)
{
if(now.x==0&&now.y==0)
break;
for(int i=0;i<4;i++)
{
int x=now.x+dx[i];
int y=now.y+dy[i];
if(0<=x&&x<=4&&0<=y&&y<=4&&vis[x][y]==vis[now.x][now.y]-1)
{
v.push_back(point(x,y));
now.x=x;
now.y=y;
break;
}
}
}
vector<point>::reverse_iterator it=v.rbegin();
printf("(%d, %d)",it->x,it->y);
it++;
for(;it!=v.rend();it++)
printf("\n(%d, %d)",it->x,it->y);
}
int main()
{
int maze[5][5];
for(int i=0;i<5;i++)
for(int j=0;j<5;j++)
cin>>maze[i][j];
bfs(maze);
print();
return 0;
}