迷宫问题

NYOJ--58题最少步数

迷宫问题有深度搜索和广度搜索两种办法。
今天在这里记录下的是广度搜索,因为广度搜素搜索到的是最短路径。
成功代码
方法一

#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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值