问题描述:
东东有一张地图,想通过地图找到终点。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是终点,这两个位置保证为0。既然已经知道了地图,那么东东找到终点就不难了,请你编一个程序,写出东东找到终点的最短路线。
input: 输入是一个5 × 5的二维数组,仅由0、1两数字组成,表示法阵地图。
output: 输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示。数据保证有唯一解。
解题思路:
首先看到这题目,已知是5*5的地图,那么就可以用一个静态数组来存储该地图。并且在行走过程中要存储点的坐标,所以定义一个结构体来表示这个坐标,其中有横坐标x和纵坐标y两个成员。
并且对于这个问题来说,由于要找到最短路径,则我们可以想到用广度优先搜索bfs,因为bfs是一层一层的遍历,所以得到的路径肯定是最短的。在bfs过程中,我们要考虑一个点有没有走过,则我们用一个vis二维数组来进行标记,一开始初始化为0,如果走到该点则进行标记,将vis数组的值赋为1。在该迷宫中。每一次bfs要考虑四个方向,上下左右依次去访问,这四个方向可以表示在坐标的变换上,则我们定义两个数组,来表示x和y坐标的变化。由于要储存坐标,则用一个结构体类型的数组from来存储该坐标的上一个位置,这样我们我们有一个位置就能找到其上一个位置,以便于最后输出。
在每一次bfs中,我们都要特判终点,如果x和y坐标都为5,则退出。如果不是,在进行坐标变换时,都必须保证坐标在迷宫内,并且没有障碍物和标记,这样才能将其压入队列。在将其压入队列时,记录该点from数组的值,并将vis数组的值标记为1。
在输出时,定义一个vector数组,从终点开始,依据from数组的值,不断寻找其上一个元素,并将其插入vector数组末尾,知道起点位置,然后将vector数组进行倒叙输出。
解题总结:
在这个题目当中,想到用bfs是该题目的突破口,并且怎样在bfs过程中保留路径是一个难题,通过一个数组,数组的下标就是该坐标,其值为其上一个可到达的点,这样就可以不断调用该数组,进行结果输出。
代码:
#include<iostream>
#include<queue>
using namespace std;
struct local{ //坐标结构体
int x;
int y;
};
int a[6][6]; //迷宫数组
int vis[6][6]; //该点是否可到达
int move_x[]={1,-1,0,0};
int move_y[]={0,0,1,-1};
local from[6][6]; //存储上一个位置
int main()
{
for(int i=1;i<=5;i++)
{
for(int j=1;j<=5;j++)
vis[i][j]=0;
}
//输入迷宫
for(int i=1;i<=5;i++)
{
for(int j=1;j<=5;j++)
cin>>a[i][j];
}
queue<local> store;
vis[1][1]=1; //将起点标记
local ll;
from[1][1]=ll;
ll.x=1;
ll.y=1;
store.push(ll);
vis[1][1]=1;
while(!store.empty())
{//bfs
local temp=store.front();
store.pop();
//特判终点
if((temp.x==5)&&(temp.y==5))
break;
//访问周围四个点
for(int i=0;i<4;i++)
{
int newx=temp.x+move_x[i];
int newy=temp.y+move_y[i];
//判断该点是否合法
if(newx>=1&&newx<=5&&newy>=1&&newy<=5&&vis[newx][newy]==0&&a[newx][newy]==0)
{
local tt;
tt.x=newx;
tt.y=newy;
store.push(tt);
from[newx][newy]=temp;
vis[newx][newy]=1;
}
}
}
vector<local> p;//路线保留在数组中
int n_x=5,n_y=5;
while((n_x!=1)||(n_y!=1))
{
local qq;
qq.x=n_x;
qq.y=n_y;
p.push_back(qq);
int te;
te=from[n_x][n_y].x;
n_y=from[n_x][n_y].y;
n_x=te;
}
p.push_back(ll);
for(int i=p.size()-1;i>=0;i--)//倒序输出
{
cout<<"("<<p[i].x-1<<", "<<p[i].y-1<<")\n";
}
}