题目:B:迷宫问题
总时间限制: 1000ms 内存限制: 65536kB
描述
定义一个二维数组:
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的二维数组,表示一个迷宫。数据保证有唯一解。
输出
左上角到右下角的最短路径,格式如样例所示。
样例输入
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
样例输出
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
解题思路:利用的就是广度优先搜索的方法,从(0,0)开始所有可能的路径都添加到队列中,由于要记录路径,所以队列是用数组实现的,每个状态都应该存储下来,而不能使用queue状态一出队列就没有了;数组通过qHead和qTail实现了队列相同的原理;建立了Node,来存储当前x,y坐标以及其父节点在队列中的位置;加入到队列中的状态就应该立马添加标记。
#include<iostream>
#include<cstring>
using namespace std;
int visited[5][5];//判重标记
struct Node
{
int x;//当前的坐标
int y;
int father;//记录父节点在状态队列中的位置
Node(int x, int y, int f):x(x),y(y),father(f){}
Node(){}
};
Node myQueue[25];//状态队列
int qHead, qTail;//队头指针和队尾指针
int main()
{
int a[5][5];//存储迷宫
for(int i = 0; i < 5; i++)
for(int j = 0; j < 5; j++)
cin >> a[i][j];
memset(visited, 0, sizeof(visited));//清零
qHead = 0;
qTail = 1;
myQueue[qHead] = Node(0, 0, -1);//起始节点的父节点标记为-1,添加到队列中(题目保证有解,所以a[0][0]一定是0)
visited[0][0] = 1;//添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
while(qHead != qTail)//队列不为空
{
if(myQueue[qHead].x == 4 && myQueue[qHead].y == 4)//找到目标状态
{
int i = qHead, route[25], num = 0;
while(myQueue[i].father != -1)//从后往前找到路径存储下来,直到起始节点为止
{
route[num] = myQueue[i].father;//存储父节点在状态队列的位置
i = myQueue[i].father;//指向父节点
num++;
}
for(int j = num - 1; j >= 0; j--)
{
cout << "(" << myQueue[route[j]].x << ", " << myQueue[route[j]].y << ")" <<endl;
}
cout << "(4, 4)";//route是从目标节点父节点位置开始存储的,所以最后要记得把目标节点也输出
system("pause");
return 0;//main()中return,程序结束
}
//不是目标节点,则扩展当前队头节点
//尝试上下左右四种移动
if(a[myQueue[qHead].x - 1][myQueue[qHead].y] == 0 && myQueue[qHead].x >= 1 && !visited[myQueue[qHead].x - 1][myQueue[qHead].y])
{//能够上移,且节点未被加入队列(未被访问过)
myQueue[qTail] = Node(myQueue[qHead].x - 1, myQueue[qHead].y, qHead);//
//添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
visited[myQueue[qHead].x - 1][myQueue[qHead].y] = 1;
qTail++;//队尾指向下一个空的位置
}
if(a[myQueue[qHead].x + 1][myQueue[qHead].y] == 0 && myQueue[qHead].x <= 3 && !visited[myQueue[qHead].x + 1][myQueue[qHead].y])
{//能够下移,且节点未被加入队列(未被访问过)
myQueue[qTail] = Node(myQueue[qHead].x + 1, myQueue[qHead].y, qHead);//
//添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
visited[myQueue[qHead].x + 1][myQueue[qHead].y] = 1;
qTail++;//队尾指向下一个空的位置
}
if(a[myQueue[qHead].x][myQueue[qHead].y - 1] == 0 && myQueue[qHead].y >= 1 && !visited[myQueue[qHead].x][myQueue[qHead].y - 1])
{//能够左移,且节点未被加入队列(未被访问过)
myQueue[qTail] = Node(myQueue[qHead].x, myQueue[qHead].y - 1, qHead);//
//添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
visited[myQueue[qHead].x][myQueue[qHead].y - 1] = 1;
qTail++;//队尾指向下一个空的位置
}
if(a[myQueue[qHead].x][myQueue[qHead].y + 1] == 0 && myQueue[qHead].y <= 3 && !visited[myQueue[qHead].x][myQueue[qHead].y + 1])
{//能够右移,且节点未被加入队列(未被访问过)
myQueue[qTail] = Node(myQueue[qHead].x, myQueue[qHead].y + 1, qHead);//
//添加到队列中了,只要不到目标节点,总会被扩展到,则不能再一次被加入队列,所以要视为已扩展
visited[myQueue[qHead].x][myQueue[qHead].y + 1] = 1;
qTail++;//队尾指向下一个空的位置
}
qHead++;//队头变为下一个元素
}
system("pause");
return 0;
}