深搜与广搜

Posted 175426-hzau-zxjc-con

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深搜与广搜相关的知识,希望对你有一定的参考价值。

 

DFS(深度优先搜索)

  从起点出发,朝任一个可能的方向走,走过的点要做标记,一直向前走。若走不了了,就回退一步,从这一个状态走向没有走过的另一个方向。

之所以称为深度优先搜索,因为它是朝着一个方向一直走到底,以深度优先,然后回溯。

DFS一般用的是递归的方法。

迷宫问题

给一个迷宫,0表示道路,1表示墙壁,找出一条从左上角到右下角的最短路径   

 

首先建立一个next[4][2]数组,表示下一步要走的方向,自定义方向的优先级,本题是从左上到右下,

那么,我可以按照下,右,上,左的顺序,则next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

遍历四个方向的代码为

for(int i=0;i<4;i++)  
    tx=x+next[i][0];ty=y+next[i][1];//x,y为当前位置坐标,tx,ty为下一步要走的坐标

或者建立两个一维数组
int nx[4]={0,1,0,-1},ny={1,0,-1,0};
for(int i=0;i<4;i++)
    {
        int tx=x+nx[i],ty=y+ny[i];
    }

还需要建立一个bool类型的vis[maxn][maxn]数组,来判断是否已经走过这条路

int nx[4]={0,1,0,-1},ny={1,0,-1,0};
void judge(int x,int y)//判断是否越界和是否已经走过
{
    return x>=0&&y>=0&&x<=n&&y<=m&&v[x][y]==0;//n为行数,m为列数
}
void dfs(int x,int y,int step)
{
    if(x==end1&&y==end2)//到达终点
    {
        ans=min(ans,step);
        return;
    }
    v[x][y]=1;//标记为走过
    for(int i=0;i<4;i++)
    {
        int tx=x+nx[i],ty=y+ny[i];
        if(judge(tx,ty))
        {
            dfs(tx,ty,step+1);//更新步数
        }
    }
    v[x][y]=0;//回退时,清除标记,
}

  给出n个正整数a1,a2....an,和一个正整数k,问是否能从这n个数中选取若干个,使其和为k

int ans=0,a[N],b[N],sum=0,step=0;//ans表示有几种情况,step代表每种情况需要几个数使其和为k
void dfs(int i,int sum,int step)
{
    if(i==n+1)//当i等于n时,因为又递归了一次,所以要判断是否等于n+1,注意只有在n个数全部都枚举完了再判断sum是否等于k
    {
        if(sum==k)
        {
            ans++;
            b[ans]=step;
        }
        return;
    }
    dfs(i+1,sum+a[i],step+1);//加上a[i]的情况,数量加1
    dfs(i+1,sum,step);//不加a[i]的情况
}

因为DFS采用递归的方法,所以很费时间,如果不剪枝的话,是很难AC的;

最简单的剪枝是sum>k时,直接返回

 

 
 
 
 
BFS(广度优先搜索),是一种利用队列(用队列来保存未访问的结点,先进先出)实现的搜索算法。简单来说,其搜索过程和 “湖面丢进一块石头激起层层涟漪” 、“树的层次遍历”类似。从源顶点s出发,依照层次结构,逐层访问其他结点。即访问到距离顶点s为k的所有节点之后,才会继续访问距离为k+1的其他结点。
bfs是按状态的层次进行扩展的,所以第一次访问到的终点节点所需步数,一定为最小步数
void bfs(初始状态)
{
 新建队列q;
 初始状态入队;
 while(队列为空)
 {
  取出队首状态;出队;
  if(到达目标状态) {跳出循环;}
  for(遍历下一层状态)
  {
   if(该状态未被访问) 入队;
   ...
  }
 }
struct node
{
    int x,y,dis;
    node(int a,int b,int c):x(a),y(b),dis(c){}
}start;
int bfs(node start)
{
    bool v[siz][siz]={0};
    queue<node>q;
    q.push(start);
    v[start.x][start.y]=1;
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        if(now.x==endx&&now.y=endy)
            return now.dis;
        for(int i=0;i<4;i++)
        {
            int tx=now.x+dx[i],ty=now.y+dy[i];
            if(can-move(tx,ty))
            {
                v[tx][ty]=1;
                node newnode(tx,ty,dis+1);
                q.push(newnode);
            }
        }
    }
    return -1;
}

 

 





















以上是关于深搜与广搜的主要内容,如果未能解决你的问题,请参考以下文章

图的广搜与深搜模板

宽搜和广搜

leetcode 深搜广搜

7.23 深搜广搜

深搜和广搜的原理及优缺点

965. 单值二叉树(深搜/广搜)