前一阵一直想写这个程序,一直没有有效的解决保存路径的问题。现在想到的办法是用队列保存每个节点的下表来表示路径。
这个算法解决问的问题是: 建一个迷宫(用矩阵表示m行,n列)期中矩阵的左上角(坐标为(0,0的点)为入点,找寻到所有到(m-1,n-1)的所有不重复路径,并打印出来。
代码注释如下
#include<iostream>
#include<deque>
using namespace std;
deque<int> Q;//用于保存路径的队列
struct node{//用于创建矩阵的结点
int x,y;//每个节点的下标
char color;//节点的颜色 (H表示可以通过,B表示墙)
};
void print();//用于打印路径的函数
bool f(int i,int j,int m,int n);//判断是否超越迷宫的边界
void search(node**p,int i,int j,int m,int n);//深度优先搜索
void main(){
int m,n;
cout<<" 输入矩阵的情况:"<<endl;
cin>>m>>n;
node**p=new node*[m];
for(int i=0;i<m;i++)
p[i]=new node[n];
for(i=0;i<m;i++){//初始化迷宫矩阵
for(int j=0;j<n;j++)
cin>>p[i][j].color;
p[i][j].x=i;
p[i][j].y=j;
}
Q.push_back(0);//将入点坐标压入队列
Q.push_back(0);
search(p,0,0,m,n);//搜索
}
void print(){
deque<int>::iterator p;
int count=0;
for(p=Q.begin();p!=Q.end();p++){
count++;
cout<<*p;
if(count%2==0) cout<<endl;
}
}
bool f(int i,int j,int m,int n){
if(i>=m||i<0) return false;
if(j<0||j>=n) return false;
return true;
}
void search(node**p,int i,int j,int m,int n){
deque<int>::iterator t;
if(i==m-1&&j==n-1){//若是出点 打印路径
print();
return; //返回至上一层递归
}
if(f(i,j-1,m,n)&&p[i][j-1].color=='H'){//若左边可以到达
p[i][j].color='B';//令此处为墙
t=Q.end();//令t为当前队列末端
Q.push_back(i);//向左移动并保存路径
Q.push_back(j-1);
search(p,i,j-1,m,n);//继续搜索
p[i][j].color='H';//回到原处
Q.erase(t,Q.end()); //删除路径记录
}
if(f(i,j+1,m,n)&&p[i][j+1].color=='H'){//若右边可以到达
p[i][j].color='B';
t=Q.end();
Q.push_back(i);
Q.push_back(j+1);
search(p,i,j+1,m,n);
p[i][j].color='H';
Q.erase(t,Q.end());
}
if(f(i-1,j,m,n)&&p[i-1][j].color=='H'){//若上边可以到达
p[i][j].color='B';
t=Q.end();
Q.push_back(i-1);
Q.push_back(j);
search(p,i-1,j,m,n);
p[i][j].color='H';
Q.erase(t,Q.end());
}
if(f(i+1,j,m,n)&&p[i+1][j].color=='H'){//若下边可以到达
p[i][j].color='B';
t=Q.end();
Q.push_back(i+1);
Q.push_back(j);
search(p,i+1,j,m,n);
p[i][j].color='H';
Q.erase(t,Q.end());
}
}
算法核心可以简述为 把当前位置设置为“墙”的目的是:如果找到了终点,那么会得到答案,如果是堵死的,那么这条路不可走,相当于墙,直接堵死以免在之后的搜索中重复