走迷宫bfs广搜

8 篇文章 0 订阅
8 篇文章 0 订阅

题目:少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。
下图 显示了一个迷阵的样例及李逍遥找到仙药的路线.
 

Input

输入有多组测试数据. 每组测试数据以两个非零整数 M 和 N 开始,两者均不大于20。M 表示迷阵行数, N 表示迷阵列数。接下来有 M 行, 每行包含N个字符,不同字符分别代表不同含义:
1) ‘@’:少年李逍遥所在的位置;
2) ‘.’:可以安全通行的方格;
3) ‘#’:有怪物的方格;
4) ‘*’:仙药所在位置。
当在一行中读入的是两个零时,表示输入结束。

Output

对于每组测试数据,分别输出一行,该行包含李逍遥找到仙药需要穿过的最少的方格数目(计数包括初始位置的方块)。如果他不可能找到仙药, 则输出 -1。

Sample

input

8 8
.@##...#
#....#.#
#.#.##..
..#.###.
#.#...#.
..###.#.
...#.*..
.#...###
6 5
.*.#.
.#...
..##.
.....
.#...
....@
9 6
.#..#. 
.#.*.# 
.####. 
..#... 
..#... 
..#... 
..#... 
#.@.## 
.#..#. 
0 0
 

output

10
8
-1
 

深度优先搜索算法(本题不适合,但还是可以做出正确结果,但是会超时 time limited)

#include<iostream> 
#include<bits/stdc++.h>
using namespace std;
int v[50][50];
char mm[50][50];
int sx,sy=0;
int minn=99999999;
int m,n,x=0;
int dx[4]={1,-1,0,0};//向 下 右 左 上 四个方向移动 
int dy[4]={0,0,1,-1};
int flag=0;//判断是否找到解药的标记 
void dfs(int x,int y,int step)
{  
/*for(int i=0;i<m;i++)
  {
   for(int j=0;j<n;j++)  //可以把这个注释解除看一看效果哟,可以清楚得看到代码的移动,1表示深搜寻找移动的方向 
   {
    cout<<v[i][j]<<" ";
   } cout<<endl;
  } cout<<"***********************"<<endl; */
 if(mm[x][y]=='*') 
 { 
  //如果找到了*,就标记1,意为已经找到 
  flag=1;
  if(step<minn)//如果发现step比minn还要小,就将最小值替换为step,因为他题目要求找到解要所需要最小路径 
  {
  	minn=step;  
  }
  return;
 }
 
 for(int i=0;i<4;i++)
 {
  int tx=x+dx[i];
  int ty=y+dy[i];
  if(tx<0||ty<0||tx>=m||ty>=n||v[tx][ty]||mm[tx][ty]=='#') //如果越界或者碰到墙,就暂停 
  {
   continue; 
  }
  v[tx][ty]=1;//将该点标记为1,已经到达 
  dfs(tx,ty,step+1);//进入深搜,步数+1 
  v[tx][ty]=0;//回退,恢复原来的路径 
 }
 return ;
}
int main()
{
 cin>>m>>n;//输入地图的大小 
 while(m&&n)  
 {
  for(int i=0;i<m;i++)
  {
   for(int j=0;j<n;j++)
   {
    cin>>mm[i][j];//将地图导入数据 
    if(mm[i][j]=='@') 
    {
     sx=i;sy=j;//记录出发点的位置为进入深搜做准备 
    }
   }
  }
  v[sx][sy]=1;//进入前地图标记为1 
  dfs(sx,sy,0);//0表示步数,一开始从出发点,步数为走,为0 
  if(flag==1)//说明找到
  {
  cout<<minn<<endl;
   } 
  else cout<<"-1"<<endl; //找不到,标记为-1 
  flag=0;
   memset(v,0,sizeof(v)); //将mm和v二维数组全部恢复默认值0 
  memset(mm,0,sizeof(mm)); 
  cin>>m>>n;
 }
  return 0;
 } 

 广度优先搜索

#include<bits/stdc++.h>//bfs函数中,先建立自定义结构体stu的队列
//将出发点位置和步数0存到对象s1中,本代码中s1和s2用来不断模拟队首出队(s1)和入队(s2) 
//将s1入队,判断队列是否为空,若不为空,队首出队
//以出队的位置为原点,向 右下左上 四个方向分别移动,

//先打比方,先向右移动一格,先判断原点右一格的位置是否满足“通路的条件” ,
//若不满足,continue回到for循环,继续向“下”的方向遍历 
//若满足 ,则在v地图上标记v[tx][ty]=1,记录为已经走过 ,并将这个位置 称为结构体stu类型的 对象 s2  
//当前位置s2和前个位置s1对比n+1,n是步数。 s2记录下当前位置 
//再判断一下这个位置是否为解药 ‘*’ 对应的位置,
//如果是,则记录更新从出发点到达这个位置所需要的最小步数,如果不是解药的位置,则判断完毕,
//接下来将s2压入队列,继续for循环从 原点 向下一个方向去重复查找 
using namespace std;
int v[100][100];//v地图初始全为0,0意为为走过,1为已经走过 
char mm[100][100];//v地图初始全为0,‘*’为解药,‘#’为墙,‘.’为通路 
int dx[4]={1,0,-1,0};//dx,dy这个数组建立,是为了向4个方向去移动 
int dy[4]={0,1,0,-1};//在bfs中自己感受它是如何向4个方向寻找的 
int minn=9999;
int m,n,s=0;//m行,n列 
struct stu{  //stu是自定义结构体的名字 
	int sx,sy,n; //创建这个结构体为后续做铺垫 
}s1,s2;//s1表示当前位置,s2表示下一个位置 
void bfs(int xx,int yy)//广搜 
{//先创建一个存储结构体的队列,中间stu表面这个是一个存储stu这个类型结构体的队列 
    queue<stu>ss;//申请队列 
	int tx,ty;
	s1.n=0;s1.sx=xx;s1.sy=yy;
	ss.push(s1);//将出发点的结构体(包含坐标和步数)压入队列
	while(!ss.empty())//只要队列不是空,就依次反复循环地执行队列,也是本广搜的核心部分 
	{ s1=ss.front();//(将队首元素出队),表示的是队首元素,赋值给s1, 
	  ss.pop();//将队首的那个弹出(完成出队删除操作) 
	  for(int i=0;i<4;i++)//向4个方向依次遍历 
	  {
	  	tx=s1.sx+dx[i];
	  	ty=s1.sy+dy[i];
	  	if(tx<=0||ty<=0||tx>n||ty>m||v[ty][tx]==1||mm[ty][tx]=='#') continue;//判断是否超出地图或者碰到“墙”,如果是就换一个方向(continue) 
	  	v[ty][tx]=1;//如果上面条件不符合,则是通路,可以走,就在v地图中标记为1,记为已经走过 
	  	//步数+1 
	  	s2.n=s1.n+1;//s2记为下一个方向的位置,s1是原来的位置 
	  	s2.sx=tx;
	  	s2.sy=ty;
	  	if(mm[ty][tx]=='*')//碰到解药,不断比较当前步数与最小值的步数,取最小值 
	  	{
	  		
	  		minn=min(minn,s2.n);
	  		s=1;//找到结果,s记为1 
		  } ss.push(s2);//每次s1到s2移动到下一个位置后,最后都要将s2的压入队列当中 
	  	
	  }
	}
	
}
int main()
{
	int x1,y1=0;
	cin>>n>>m;//输入地图的大小 
	while(n&&m)//只要不出现0,就能执行 
	{
		for(int i=1;i<=m;i++)//将地图输入到这个mm地图当中 
		{
			for(int j=1;j<=n;j++)
			{
				cin>>mm[i][j];
				if(mm[i][j]=='@')//记录出发点的位置 
				{
					x1=j,y1=i;
				}
			}
		}//bfs肯定要把出发位置压入队列,在所有压入队列前面都要在v地图上标记为已经走过 
		v[y1][x1]=1;//出发点位置在v地图是记录值为1,已经走过 
		bfs(x1,y1);
		if(s) cout<<minn<<endl;//用s做标记判断是否找到解药,一开始标记为0,若找到解药更改为1 
		else cout<<"-1"<<endl;//找不到解药,输出-1 
		
		memset(v,0,sizeof(v));//将mm和v二维数组全部恢复默认值0 
		memset(mm,0,sizeof(mm));
		cin>>m>>n;s=0;minn=9999;//准备测试下一组数据,将这些变化恢复为初始值 
		
		
	}
 } 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值