早上考完高数(这考试好水啊),回来补上昨晚的题解。
题目描述:
题目:https://vjudge.net/problem/POJ-3984
定义一个二维数组:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
输入:
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
输出:
左上角到右下角的最短路径,格式如样例所示。
样例:
Input:
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Output:
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
思路分析:
因为这道题涉及到最短路径,所以使用BFS是比较合适的。但这道题有个特点:需要记录路径,所以,需要在我们搜到最后的时候能够找得到他的上一步。
因此,想到的方法是:通过一个数组,记下这个过程中全部经过的点。当搜到最短路路径时,通过这个点内包含的上一个点的信息,一级一级地找到上一个点(这里我尝试使用了vector来存储这些点)。这样,每个点需要记录的信息就包括:该点的横坐标,纵坐标和该点上一步的信息。可以通过建立struct来保存信息。
这样,每搜到一个点,在将这个点压入队列的同时,也压入一个vector。搜索完成后再做处理。
typedef struct{
int x;
int y;
int root;
} point;
int xx[]={1,0,-1,0};
int yy[]={0,-1,0,1};
int main()
{
bool vis[6][6]={0};
int floor[6][6]={0};
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
cin>>floor[i][j];
}
}
vector<point> temp;
point t1={0,0,-1};
queue<point> a;
temp.push_back(t1);
a.push(t1);
k=0;
//搜索、输出。
return 0;
}
下面开始搜索:
while(true)
{
if(a.front().x==4&&a.front().y==4)//到达终点,终止搜索。
{
break;
}
else
{
for(int i=0;i<4;i++)
{
int dx=a.front().x+xx[i];
int dy=a.front().y+yy[i];//点向四个方向移动生成下一个要搜的点
if(floor[dx][dy]==0&&vis[dx][dy]==0&&dx>=0&&dy>=0&&dx<5&&dy<5)//确认不会越界、没有被访问过且可以被访问。
{
vis[dx][dy]=1;//标记已被访问过
point t2={dx,dy,k};
a.push(t2);//把该点压入队列
temp.push_back(t2);//记录这一步。
}
}
a.pop();//搜索完这个点,弹出队列。
}
k++;//表示现在生成的这个点他的上一步是在数组中的哪个位置。
}
走到这,这道题也差不多了。但是,还没完:
因为它不是从终点开始输出的,所以,我们还需要通过我们现在搜到的这个点root元素往回找出它的路径,在从起点开始(相当于逆序输出)。
这里,由于我联想到了LIFO,所以采用了一个栈来保存这些点:
stack<point> result;//建立栈
result.push(a.front());//将终点压入
point*p=&temp[a.front().root];//通过指针指向找到上一个点,其实可以不用,单纯顶一个整除也行。
do
{
result.push(*p);//将这个过程中的点压入队列。
p=&temp[p->root];//继续找上一个点。
}while(p->root!=-1);//当root为-1时说明这个点是起点,在前面定义初点时留下的标记。
result.push(*p);//压入初点
while(!result.empty())//逆序输出
{
printf("(%d, %d)",result.top().x,result.top().y);
if(result.size()!=1) cout<<endl;
result.pop();
}
完毕。
完整代码
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
typedef struct{
int x;
int y;
int root;
} point;
int xx[]={1,0,-1,0};
int yy[]={0,-1,0,1};
int main()
{
bool vis[6][6]={0};
int floor[6][6]={0};
for(int i=0;i<5;i++)
{
for(int j=0;j<5;j++)
{
cin>>floor[i][j];
}
}
vector<point> temp;
point t1={0,0,-1};
queue<point> a;
temp.push_back(t1);
a.push(t1);
int k=0;
while(true)
{
if(a.front().x==4&&a.front().y==4)
{
break;
}
else
{
for(int i=0;i<4;i++)
{
int dx=a.front().x+xx[i];
int dy=a.front().y+yy[i];
if(floor[dx][dy]==0&&vis[dx][dy]==0&&dx>=0&&dy>=0&&dx<5&&dy<5)
{
vis[dx][dy]=1;
point t2={dx,dy,k};
a.push(t2);
temp.push_back(t2);
}
}
a.pop();
}
k++;
}
stack<point> result;
result.push(a.front());
//cout<<"("<<a.front().x<<","<<a.front().y<<")"<<endl;
point*p=&temp[a.front().root];
do
{
result.push(*p);
p=&temp[p->root];
}while(p->root!=-1);
result.push(*p);
while(!result.empty())
{
printf("(%d, %d)",result.top().x,result.top().y);
if(result.size()!=1) cout<<endl;
result.pop();
}
return 0;
}