迷宫问题
定义一个二维数组:
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表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample 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
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
1.DFS解法如下:
#include<iostream>
#include<stdlib.h>
#include<map>
#include<cmath>//数学
#include<queue>//队列
#include<stack>//栈
#include<iomanip>//精度控制
#include<string>//字符串
#include<vector>//容器
#include<algorithm>//算法
using namespace std;
int count=0;
int a[100][100]; //迷宫大小
int min=INT_MAX;//用来找到最短路径
typedef struct
{
int x;
int y;
}Box;//定义一个Box类来存放x,y点
Box b1[10000];//用来存储当前路径
Box b2[10000];//用来存储最短路径
int nums=0;//走的步数
bool c=false;//判断是否能走到终点
void dfs(Box cur,int count,int hang ,int lie){
int x1=cur.x;
int y1=cur.y;
if(x1==hang-1 && y1==lie-1 && min>count){//找到最短路径
c=true;//找到出口
min=count;
nums=count;//走的步数
for(int i = 0;i <=count;i++) //存路径给b2
{
b2[i].x = b1[i].x;
b2[i].y = b1[i].y;
}
}
else{
if(x1-1>=0 && a[x1-1][y1]==0){//上
a[x1][y1]=2;//将这个点标记
b1[count+1].x=x1-1;
b1[count+1].y=y1;
dfs(b1[count+1],count+1,hang,lie);
a[x1][y1]=0;//恢复现场,因为迷宫往往不只有一条路可以走,在dfs完成之后进行恢复
}
if(x1+1<hang && a[x1+1][y1]==0){//下
a[x1][y1]=2;
b1[count+1].x=x1+1;
b1[count+1].y=y1;
dfs(b1[count+1],count+1,hang,lie);
a[x1][y1]=0;
}
if(y1-1>=0 && a[x1][y1-1]==0){//左
a[x1][y1]=2;
b1[count+1].x=x1;
b1[count+1].y=y1-1;
dfs(b1[count+1],count+1,hang,lie);
a[x1][y1]=0;
}
if(y1+1<lie && a[x1][y1+1]==0){//右
a[x1][y1]=2;
b1[count+1].x=x1;
b1[count+1].y=y1+1;
dfs(b1[count+1],count+1,hang,lie);
a[x1][y1]=0;
}
}
}
int main(){
int hang,lie;
cin>>hang>>lie;
for(int i=0;i<hang;i++){
for(int j=0;j<lie;j++){
cin>>a[i][j];//输入行列数
}
}
b1[0].x=0;//起点设置为0,0
b1[0].y=0;
dfs(b1[0],0,hang,lie);
if(c==1){
for(int k = 0;k <=nums;k++)
cout<<b2[k].x<<","<<b2[k].y<<endl;}
else{
cout<<"这个迷宫没有出口"<<endl;
}
}
2.BFS解法:
第一版:只能判断是否能走出迷宫,不能输出如何走的坐标
#include<iostream>
#include<stdlib.h>
#include<map>
#include<cmath>//数学
#include<queue>//队列
#include<stack>//栈
#include<iomanip>//精度控制
#include<string>//字符串
#include<vector>//容器
#include<algorithm>//算法
using namespace std;
int a[100][100];
typedef struct //若要记录路径,则应该运用结点数组,每遍历一次,就往结点存当前坐标值,最后按顺序将结点输出即可得到路径
{
int x;
int y;
}Box;
Box b1[10000];//用来存储当前路径
Box b2[10000];//用来存储最短路径
int nums=0;//走的步数
bool c=false;//判断是否能走到终点
void bfs(Box cur,int hang ,int lie){
Box location;
Box temp;//用来存合格的值并返回
queue<Box> A;//创建一个以Box对象为载体的队列
A.push(cur);
while(!A.empty()){
location=A.front();//location也是Box对象
if(location.x==hang-1 && location.y==lie-1){//已经到达出口
c=true;//找到出口
break;
}
A.pop();
if(location.x-1>=0 && a[location.x-1][location.y]==0){//上
a[location.x][location.y]=2;
temp.x=location.x-1;
temp.y=location.y;
A.push(temp);
}
if(location.x+1<hang && a[location.x+1][location.y]==0){//下
a[location.x][location.y]=2;
temp.x=location.x+1;
temp.y=location.y;
A.push(temp);
}
if(location.y-1>=0 && a[location.x][location.y-1]==0){//左
a[location.x][location.y]=2;
temp.x=location.x;
temp.y=location.y-1;
A.push(temp);
}
if(location.y+1<lie && a[location.x][location.y+1]==0){//右
a[location.x][location.y]=2;
temp.x=location.x;
temp.y=location.y+1;
A.push(temp);
}
}
}
int main(){
int hang,lie;
cin>>hang>>lie;
for(int i=0;i<hang;i++){
for(int j=0;j<lie;j++){
cin>>a[i][j];//输入行列数
}
}
b1[0].x=0;
b1[0].y=0;
bfs(b1[0],hang,lie);
if(c==1){
cout<<"有出口"<<endl;
}
else{
cout<<"这个迷宫没有出口"<<endl;
}
}
2.正确版本BFS,可以进行正确的输出
#include<iostream>
#include<stdlib.h>
#include<map>
#include<cmath>//数学
#include<queue>//队列
#include<stack>//栈
#include<iomanip>//精度控制
#include<string>//字符串
#include<vector>//容器
#include<algorithm>//算法
using namespace std;
int count=0;
int hang,lie;
int a[100][100]; //迷宫大小
int min=INT_MAX;
typedef struct //应该运用结点数组,每遍历一次,就往结点存当前坐标值,最后按顺序将结点输出即可得到路径
{
int x;
int y;
int pre;//指向前方的指针
}Box;
typedef struct{
Box data[10000];//将Box类型包含在其中
int head;//头节点
int tail;//尾结点
}Queue;
bool c=false;//判断是否能走到终点
void print(Queue qu, int cur)//用来找出原来的路径,反向找到这一条路径,因为存入的顺序与输出是相反的
{
int j=cur,k;
while(j!=0){
k=j;
j=qu.data[k].pre;//将j指向qu.data[k]的前一个
qu.data[k].pre=-1;//将这个元素的pre设置为-1用来输出,因为我们第一步设置的head就是-1
}
while(j<400){//假设的是20*20行
if(qu.data[j].pre==-1){//如果pre是-1就进行输出
cout<<qu.data[j].x<<","<<qu.data[j].y<<endl;
}
j++;
}
}
void bfs(int x,int y,int hang,int lie){
Queue l1; //创建队列
l1.tail = 0; //初始化队列
l1.head = -1; //因为头指针开始时不应该与tail指向同一位置
l1.data[0].x = 0;
l1.data[0].y = 0;
l1.data[0].pre = -1; //初始结点的pre设为-1,作为输出路径的递归出口
a[x][y]=2;//将x,y点标记
while(l1.head != l1.tail && c!=1){
l1.head++;//head指向出队节点
int p=l1.data[l1.head].x;//用l1.head作为data数组的下标
int q=l1.data[l1.head].y;
if(p==hang-1 && q==lie-1){//已经到达终点
c=true;
print(l1,l1.head);
}
else{
if(p-1>=0 && a[p-1][q]==0){//上
a[p][q]=2;
l1.tail++;//尾指针后移
l1.data[l1.tail].x=p-1;//用尾指针来作为data下标
l1.data[l1.tail].y=q;
l1.data[l1.tail].pre=l1.head;//将data[l1.tail]的pre指针指向前一个的head
}
if(p+1<hang && a[p+1][q]==0){//下
a[p][q]=2;
l1.tail++;
l1.data[l1.tail].x=p+1;
l1.data[l1.tail].y=q;
l1.data[l1.tail].pre=l1.head;
}
if(q-1>=0 && a[p][q-1]==0){//左
a[p][q]=2;
l1.tail++;
l1.data[l1.tail].x=p;
l1.data[l1.tail].y=q-1;
l1.data[l1.tail].pre=l1.head;
}
if(q+1<lie && a[p][q+1]==0){//右
a[p][q]=2;
l1.tail++;
l1.data[l1.tail].x=p;
l1.data[l1.tail].y=q+1;
l1.data[l1.tail].pre=l1.head;
}
}
}
}
int main(){
cin>>hang>>lie;
for(int i=0;i<hang;i++){
for(int j=0;j<lie;j++){
cin>>a[i][j];//输入行列数
}
}
bfs(0,0,hang,lie);
if(c==1){
cout<<"有出口"<<endl;
}
else{
cout<<"这个迷宫没有出口"<<endl;
}
}
总结:可以使用这种结构体来储存数据
typedef struct //应该运用结点数组,每遍历一次,就往结点存当前坐标值,最后按顺序将结点输出即可得到路径
{
int x;
int y;
int pre;//指向前方的指针
}Box;
typedef struct{
Box data[10000];//将Box类型包含在其中
int head;//头节点
int tail;//尾结点
}Queue;
并且也可以创造以这种数据为载体的队列
typedef struct
{
int x;
int y;
}Box;
queue<Box> A;