bfs的算法的详解(代码版)

bfs就是所谓的广度搜索( Breadth first search),这种算法旨在解决最优问题,如最小时间,最快路径之类的。实际上dfs(深度优先搜索)也是可以解决此类问题(这个可以参考下一篇),但是鉴于题目的空间和时间的限制,你不得不选择bfs(深搜同样也能解决最优问题,但是他是将所有的结果都找出来,那么时间上你已经gg了)

简单来说,这个算法就是将地图上能走的点走一遍,找出最优的解。步骤的话,就是创建2维数组,作为地图,然后找到起点和终点,从起点开始,输入每个点。然后进行判断。这个一点是不是符合要求,然后标记这个点已经走过了。

(为了明显区分两种算法的区别,我这里使用结构体的知识来完成这个算法)

关于这个算法,根据我上面所说,你可以分成4部分来完成。第一部分当然是最简单的读入地图

int a[100][100],v[100][100];//a是地图。v是标记地图有没有走过 
scanf("%d%d",&n,&m);	
for(int i=1;i<=n;i++)	
for(int j=1;j<=m;j++)	
scanf("%d",&a[i][j]);

地图可能是字符也可能是数字(当然在这里i=0,i<n,也是可以的)
所以也可以这样输入(下面那个是解决字符串情况的)

scanf("%d%d",&n,&m); 
for(int i=0;i<n;i++)
scanf("%s",a[i]) 

当然,如果,你不是很确定自己的地图输入是否有问题的话,你可以选择输出,去检测

然后 就是去寻找终点和起点,然后记录下来。当然,有些题目是会让你直接输入终点和起点的。。但是大部分还是要自己找。

            for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                if(a[i][j]=='@')
                {
                    startx=i;
                    starty=j;
                }
                if(a[i][j]=='*')
                {
                    p=i;
                    q=j;
                    a[i][j]='.';
                   
                }
            }
      

这里有个细节就是,如果你找到终点的话,那么要将终点变成能走的地区,否则,你最后的步数会少1
因为,终点他是不会走的。(正常的代码都是找到终点后就直接结束,当然,你也可以选择在最后在加1上去。效果也是一样的)

然后就是最重要的dfs部分了。

struct point
{	int x;	
     int y;
	int step;};
	queue<point>r;//申请队列
	 int dx[4]={0,1,0,-1};//顺时针右 下左上 
	 int dy[4]={1,0,-1,0};

你要先定义结构体。dx和dy的话就作为方向。dfs的话要那么逆时针要么顺时针走,

point start;
start.x=startx;	//start是起点
start.y=starty;
start.step=0;	
r.push(start);//入队
v[startx][starty]=1;
 	
int flag =0;//这个是用来判断能不能到终点的,如果能就是1 	
while(!r.empty())//如果队列不为空的话,那么久执行	
{		
int x=r.front().x;		
int y=r.front().y;		
if(x==p&&y==q)	{			
flag=1;			
printf("%d",r.front().step);	
	}		
	for(int k=0;k<=3;k++)//这里是3个方向,		
	{			int tx,ty;			
	                        tx=x+dx[k];			
	                        ty=y+dy[k];			
	                        if(a[tx][ty]==1&&v[tx][ty]==0)//是空地并且未访问 			
	                        {				//入队				
	                        point temp;				
	                        temp.x=tx;				
	                        temp.y=ty;				
	                        temp.step=r.front().step+1;				
	                        r.push(temp);				
	                        v[tx][ty]=1; 			
	                        }		
	                        }		
	                        r.pop();//出队 
	                        	}	
	                        if(flag==0)	
	                        printf("no");	
	                        return 0;
	                        } 
	        
	
这里还要注意的就是,如果你是处理守卫问题的话(即打败一个守卫会花费1一个时间单位),会遇到一个问题,这是路程最短,
但不是时间最短。那么你需要在前面加一个判断,如果是是守卫的话,时间加1
,但是不标记守卫走过。然后将守卫变成能走的路即可


完整的代码是这样的:
//这个代码旨在解决一个出口,一个起点,找到最小的路径的问题

#include<bits/stdc++.h>
using namespace std;
int a[100][100],v[100][100];//a是地图。v是标记地图有没有走过 
struct point
{
 int x;
 int y;
 int step;
};
queue<point>r;//申请队列 
int dx[4]={0,1,0,-1};//顺时针右 下左上 
int dy[4]={1,0,-1,0};
int main()
{
 int n,m,startx,starty,p,q;
 scanf("%d%d",&n,&m);
 for(int i=1;i<=n;i++)
 for(int j=1;j<=m;j++)
 scanf("%d",&a[i][j]);
 
 scanf("%d%d%d%d",&startx,&starty,&p,&q);
 //bfs
 point start;
 start.x=startx;
 start.y=starty;
 start.step=0;
 r.push(start);//入队 
 v[startx][starty]=1;
 int flag =0; 
 while(!r.empty())
 {
  int x=r.front().x;
  int y=r.front().y;
  if(x==p&&y==q)
  {
   flag=1;
   printf("%d",r.front().step);
  }
  for(int k=0;k<=3;k++)
  {
   int tx,ty;
   tx=x+dx[k];
   ty=y+dy[k];
   if(a[tx][ty]==1&&v[tx][ty]==0)//是空地并且未访问 
   {
    //入队
    point temp;
    temp.x=tx;
    temp.y=ty;
    temp.step=r.front().step+1;
    r.push(temp);
    v[tx][ty]=1; 
   }
  }
  r.pop();//出队 
 }
 if(flag==0)
 printf("no");
 return 0;
 } 
  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值