C.就来谈谈深搜与广搜

C.深搜与广搜的基础代码实现

下面以一道简单的搜索算法题为例:
在一个,迷宫中寻找出口,并且要求路径最短。且迷宫中有障碍物不能穿过,并由规定起点出发。输入包括三部分,第一行:迷宫的尺寸大小。
第二行:定义迷宫。 第三行:起始位置和出口所在。

深搜代码实现部分:

#include<stdio.h>
int n,m,p,q,min=9999;
int a[51][51],book[51][51];//a用来储存迷宫,book用来记录已走过的路径。
int sum;//记录所有出口的方式。
void dfs(int x,int y,int step);//深搜函数。
int main()
{
    int i,j,startx,starty;
    scanf("%d %d",&n,&m);//输入迷宫大小。
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        scanf("%d",&a[i][j]);//编辑迷宫。
    scanf("%d %d %d %d",&startx,&starty,&p,&q);//初始坐标和出口赋值。
    book[startx][starty]=1;//初始坐标已走过避免再次搜索。
    dfs(startx,starty,0);//传递参数。
    printf("%d\n",min);
    printf("%d\n",sum);
    system("pause");
    return 0;
}
void dfs(int x,int y,int step)
{
    int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//分别定义上下左右四个方向。
    int tx,ty,k;//[tx][ty]表示下一步坐标,k为了遍历所有方向
    if(x == p && y == q)//判断是否为出口
    {
        if(step < min)
        {
            min = step;//更新最短路径
        }
        sum++;//找到出口sum+1
        return;
    }
    for(k=0;k<=3;k++)
    {
        tx = x + next[k][0];
        ty = y + next[k][1];
        if(tx < 1 || tx > n || ty < 1 || ty > m)//如果越界不再进行下一步,直接寻找其他未越界的方向
        {
            continue;
        }
        if(a[tx][ty] == 0 && book[tx][ty] == 0)//判断该方向是否可以继续行走
        {
            book[tx][ty] = 1;//记录当前坐标已走过
            dfs(tx,ty,step+1);//在当前基础上进行下一步搜索
            book[tx][ty] = 0;//遍历过该方向便收回以方便其左边搜索时可以行走
        }
    }
    return;
}

以上为深搜的实现代码,带有注释应该是不难理解的。那么下面就来看看广搜吧,并从中发现他们的不同所在吧。

广搜代码实现部分:

#include<stdio.h>
struct note//队列
{
    int x;//横坐标
    int y;//纵坐标
    int f;//父节点(上一个结点)
    int s;//步数
};
int main()
{
    struct note que[2501];//定义队列
    int a[51][51]={0},book[51][51]={0};//定义迷宫数组,book用于记录哪些点已遍历过
    int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//分别代表向右,想下,向左,向上
    int head,tail;//head表示正扩展的结点,tail位于队尾最后一个元素的后面随时将head扩展出来的结点入队
    int i,j,k,n,m,startx,starty,p,q,tx,ty,flag;
    scanf("%d %d",&n,&m);//迷宫规格
    for(i = 1;i <= n;i++)
        for(j = 1;j <= m;j++)
        scanf("%d",&a[i][j]);
    scanf("%d %d %d %d",&startx,&starty,&p,&q);//起点,终点
    head = 1;
    tail = 1;
    //将初始入口入队
    que[tail].x = startx;
    que[tail].y = starty;
    que[tail].f = 0;
    que[tail].s = 0;
    tail++;//每执行一次入队就后移一位
    book[startx][starty] = 1;//起点已到达过
    flag = 0;//如找到终点即flag=1,现在表示未找到终点
    while(head < tail)//队列不为空
    {
        for(k = 0;k < 4;k++)//枚举4个方向
        {
            tx = que[head].x + next[k][0];
            ty = que[head].y + next[k][1];
            if(tx < 1||tx > n||ty < 1||ty > m)//判断是否越界
                continue;
            if(a[tx][ty] == 0 && book[tx][ty] == 0)//判断是否为障碍,是否已经走过
            {
                book[tx][ty] = 1;//记录当前节点已走过,广搜每个节点只搜索一次,所以之后不需要再次置零
                que[tail].x = tx;
                que[tail].y = ty;
                que[tail].f = head;
                que[tail].s = que[head].s + 1;
                tail++;//没入队一次tail++
            }
            if(tx==p && ty==q)//是否找到出口
            {
                flag = 1;
                break;
            }
        }
        if(flag == 1)
            break;
        head++;//当前节点的扩展未有找到出口,搜索下一个节点
    }
    printf("%d\n",que[tail - 1].s);//因为tail指向队尾最后一个元素的后一位
    system("pause");//程序运行完毕,暂停检查数据
    return 0;
}

以上就是两种搜索的基本实现,从中不难看出:
深搜是属于“不撞南墙不回头”?这么说应该对的哈。总之,深搜大抵就是,有一个结点开始,选择一条分支进行深搜,当遇到下一结点重复上述步骤,知道这一分支被搜索完毕,然后再从搜索完的最下面的结点,向上回溯,如果还有其他选择,在对其他选择进行搜索。大体流程就是这样,从树的根部搜索到最末尾的分支,然后,一个节点搜索完毕后,回溯,再搜索,知道在回溯到树的根部,再由树的根部发出另一分支。搜索到目标则停止。
广搜就有别于深搜,广搜是向外发散式的搜索。就像Wi-Fi的图标,大家都是熟悉的吧,由树的根部也就是Wi-Fi的那个点一层一层的向外发散,搜索完一层,再进入下一层,直至到达最后一层。相对于深搜来说,他更显得盲目。但却并不花费更多时间,相对来说,深搜更加浪费时间。

写在最后

搜索题大体都是这样的模板,如果遇到问题仔细考虑,判断用什么搜索方法。祝愿各位奋斗在C代码海洋的同胞们有心人终成正果。

                                                                泪目°
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值