迷宫问题有深度搜索和广度搜索两种办法。 今天在这里记录下的是广度搜索,因为广度搜素搜索到的是最短路径。
成功代码
方法一
#include <iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=10; //表示迷宫的宽度和长度
const int MAX=100;
int vis[N][N]; //表示迷宫中每int一个方块是否被访问的数组
int dis[N][N];
int before[MAX]; //记录路径的数组
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
queue<int> q;
void print(int i);
void clear(queue<int> q);
void bfs(int s1,int e1,int s2,int e2);
int Mg[9][9]={
1,1,1,1,1,1,1,1,1,
1,0,0,1,0,0,1,0,1,
1,0,0,1,1,0,0,0,1,
1,0,1,0,1,1,0,1,1,
1,0,0,0,0,1,0,0,1,
1,1,0,1,0,1,0,0,1,
1,1,0,1,0,1,0,0,1,
1,1,0,1,0,0,0,0,1,
1,1,1,1,1,1,1,1,1
};
int n=9;
int num=0;
void bfs(int s1,int e1,int s2,int e2)
{
int i,j,nx,ny,cur;
int d;
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
/*每次循环前必须受到清空队列容器*/
while(!q.empty())
q.pop();
q.push(s1*n+e1);
vis[s1][e1]=1;
before[s1*n+e1]=s1*n+e1; //将路径上后序结点的before值设置为该结点的前一个结点的坐标值
dis[s1][e1]=0;
while(!q.empty())
{
cur=q.front();//取队头元素,搜索它的相邻结点
q.pop();
i=cur/n; //队头元素的行号
j=cur%n; //队头元素的列号
//否则,搜索该结点是否存在还未被访问过的结点
for(d=0;d<4;d++)
{
nx=i+dx[d]; //相邻结点的行号
ny=j+dy[d]; //相邻结点的列号
if(nx>=0 && nx<n && ny>=0 && ny<n && Mg[nx][ny]==0 && vis[nx][ny]==0)
{
q.push(nx*n+ny);
vis[nx][ny]=1;
before[nx*n+ny]=cur;
dis[nx][ny]=dis[i][j]+1;//方法二
}
}
/*可以不要*/
if(cur==s2*n+e2) //如果当前结点已经是目的结点,则直接退出
{
break;
}
}
}
void clear(queue<int> q)
{
while(!q.empty())
q.pop();
}
/*方法一*/
void print(int i)
{
if(before[i]!=i)
print(before[i]);
num++;
cout<<"("<<(i/n)<<","<<(i%n)<<")"<<endl;
}
int main()
{
int i,j,t;
int s1,e1,s2,e2;
cin>>t;
while(t--)
{
num=0;
cin>>s1>>e1>>s2>>e2;
bfs(s1,e1,s2,e2);
if(num>0)
num-=1;
cout<<num<<endl;
//cout<<dis[s2][e2]<<endl;
}
return 0;
}
方法二
#include <iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=10; //表示迷宫的宽度和长度
const int MAX=100;
int vis[N][N]; //表示迷宫中每int一个方块是否被访问的数组
int dis[N][N];
int before[MAX]; //记录路径的数组
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
queue<int> q;
void print(int i);
void clear(queue<int> q);
void bfs(int s1,int e1,int s2,int e2);
int Mg[9][9]={
1,1,1,1,1,1,1,1,1,
1,0,0,1,0,0,1,0,1,
1,0,0,1,1,0,0,0,1,
1,0,1,0,1,1,0,1,1,
1,0,0,0,0,1,0,0,1,
1,1,0,1,0,1,0,0,1,
1,1,0,1,0,1,0,0,1,
1,1,0,1,0,0,0,0,1,
1,1,1,1,1,1,1,1,1
};
int n=9;
int num=0;
void bfs(int s1,int e1,int s2,int e2)
{
int i,j,nx,ny,cur;
int d;
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
/*每次循环前必须受到清空队列容器*/
while(!q.empty())
q.pop();
q.push(s1*n+e1);
vis[s1][e1]=1;
before[s1*n+e1]=s1*n+e1; //将路径上后序结点的before值设置为该结点的前一个结点的坐标值
dis[s1][e1]=0;
while(!q.empty())
{
cur=q.front();//取队头元素,搜索它的相邻结点
q.pop();
i=cur/n; //队头元素的行号
j=cur%n; //队头元素的列号
/*可以不要*/
if(cur==s2*n+e2) //如果当前结点已经是目的结点,则直接退出
{
print(cur);
break;
}
//否则,搜索该结点是否存在还未被访问过的结点
for(d=0;d<4;d++)
{
nx=i+dx[d]; //相邻结点的行号
ny=j+dy[d]; //相邻结点的列号
if(nx>=0 && nx<n && ny>=0 && ny<n && Mg[nx][ny]==0 && vis[nx][ny]==0)
{
q.push(nx*n+ny);
vis[nx][ny]=1;
before[nx*n+ny]=cur;
}
}
}
}
void clear(queue<int> q)
{
while(!q.empty())
q.pop();
}
/*方法一*/
void print(int i)
{
if(before[i]!=i)
print(before[i]);
num++;
cout<<"("<<(i/n)<<","<<(i%n)<<")"<<endl;
}
int main()
{
int i,j,t;
int s1,e1,s2,e2;
cin>>t;
while(t--)
{
num=0;
cin>>s1>>e1>>s2>>e2;
bfs(s1,e1,s2,e2);
if(num>0)
num-=1;
cout<<num<<endl;
//cout<<dis[s2][e2]<<endl;
}
return 0;
}
方法一和方法二没有什么太大的区别,无非是一个用数组来记录距离,另一个则是每一次当找到了起点到终点的路径之后,在通过对路径进行遍历统计其长度
过程中不断出错,原因是当循环执行dfs时,队列并没有清空。所以要清空队列。当然也可以直接用数组来模拟队列,而不必用STL。