搜索(手记)

作为一个算法初学者,简单写一下对搜索的感受和经验。
搜索分为深搜和广搜两种,下面会分别介绍一下。

深搜(DFS)

从一个顶点(A)开始,标记A已经遍历,寻找临近A且没有遍历过的点(B),如果找到则继续寻找(即将B代入A),如果找不到则结束本次搜索

小小的一个提醒(提醒虽小,看懂的都是人才)

我设置了四个数组,分别解释一哈。(好好想想为什么要设置四个呢?)
brr[][]单纯的存一下地图(所以地图不能改)
flag[][]标记坐标是否可以走(所以flag会经常变。渣数组,经常变)
minn[][]存当前路径
ans[][]存答案路径

贴一段算法模板

// DFS模板
int a,b,s=0,mink=100;
int brr[10][10];
int flag[10][10],ans[100],minn[100];
int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};///可以走的几个方向
void DFS(int x,int y,int k)
{
    if(x==4&&y==4){///到达目的地
        if(k<mink){///判断是不是最短的
            mink=k;
            for(int i=0;i<=k;i++)
                ans[i]=minn[i];
        }
        return;
    }
    for(int i=0;i<4;i++){///遍历所以方向
        int ix=x+dis[i][0];
        int iy=y+dis[i][1];
        if(ix>=0&&ix<=4&&iy>=0&&iy<=4&&flag[ix][iy]==0&&brr[ix][iy]==0){///判断条件
            flag[ix][iy]=1;///下一步标记走过
            minn[k]=ix*10+iy;///存当前的坐标
            DFS(ix,iy,k+1);///判断下一步
            flag[ix][iy]=0;///解放坐标,方便下一种的可能
        }
    }
}

搞一个完整的模板(神特么有用)

///介绍一下问题,一个5*5的图,从(0,0)到(4,4)的最短路,并打印
#include<iostream>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<stack>
#include<queue>
#include<iomanip>
#include<map>
#include<set>
#include<functional>
using namespace std;
int a,b,s=0,mink=100;
int brr[10][10];
int flag[10][10],ans[100],minn[100];
int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};///可以走的几个方向
void DFS(int x,int y,int k)
{
    if(x==4&&y==4){///到达目的地
        if(k<mink){///判断是不是最短的
            mink=k;
            for(int i=0;i<=k;i++)
                ans[i]=minn[i];
        }
        return;
    }
    for(int i=0;i<4;i++){///遍历所以方向
        int ix=x+dis[i][0];
        int iy=y+dis[i][1];
        if(ix>=0&&ix<=4&&iy>=0&&iy<=4&&flag[ix][iy]==0&&brr[ix][iy]==0){///判断条件
            flag[ix][iy]=1;///下一步标记走过
            minn[k]=ix*10+iy;///存当前的坐标
            DFS(ix,iy,k+1);///判断下一步
            flag[ix][iy]=0;///解放坐标,方便下一种的可能
        }
    }
}
int main()
{
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            cin >> brr[i][j];
    memset(flag,0,sizeof(flag));
    DFS(0,0,0);
    printf("(%d, %d)\n",0,0);
    for(int i=0;i<mink;i++)
        printf("(%d, %d)\n",ans[i]/10,ans[i]%10);
    return 0;
}

广搜(BFS)

从第一个点开始进行判断,符合条件就压进队列,直到队列为空或目的达成

贴一段模板

//BFS模板
struct data{
    int x,y,k;
}now,well;
int a,b,s=0,mink=100;
int flag[10][10],brr[10][10],ans[100],minn[100];
int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};///可以走的几个方向
int BFS(data A)
{
    memset(flag,0,sizeof(flag));///标记点是否走过的地图
    A.k=0;///初始化
    queue<data> Q;
    Q.push(A);///恶梦的开始
    flag[A.x][A.y]=1;///标记初始点已经走过了
    while(!Q.empty()){
        now=Q.front();///处理第一个数据
        Q.pop();///抛弃第一个数据
        if(now.x==4&&now.y==4)///判断是否到达目的地
            return now.k;
        for(int i=0;i<4;i++){
            well.x=now.x+dis[i][0];
            well.y=now.y+dis[i][1];
            if(well.x>=0&&well.x<=4&&well.y>=0&&well.y<=4&&brr[well.x][well.y]==0&&flag[well.x][well.y]==0){
                flag[well.x][well.y]=now.k;///标记初始点已经走过了,顺便标记这个点是第几步走的
                well.k=now.k+1;///总步数加1
                Q.push(well);///压进队列
            }
        }
    }
}

搞一个完整的模板(神特么有用)

//介绍一下问题,一个5*5的图,从(0,0)到(4,4)的最短路
#include<iostream>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<stack>
#include<queue>
#include<iomanip>
#include<map>
#include<set>
#include<functional>
using namespace std;
struct data{
    int x,y,k;
}now,well;
int a,b,s=0,mink=100;
int flag[10][10],brr[10][10],ans[100],minn[100];
int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};///可以走的几个方向
int BFS(data A)
{
    memset(flag,0,sizeof(flag));///标记点是否走过的地图
    A.k=0;///初始化
    queue<data> Q;
    Q.push(A);///恶梦的开始
    flag[A.x][A.y]=1;///标记初始点已经走过了
    while(!Q.empty()){
        now=Q.front();///处理第一个数据
        Q.pop();///抛弃第一个数据
        if(now.x==4&&now.y==4)///判断是否到达目的地
            return now.k;
        for(int i=0;i<4;i++){
            well.x=now.x+dis[i][0];
            well.y=now.y+dis[i][1];
            if(well.x>=0&&well.x<=4&&well.y>=0&&well.y<=4&&brr[well.x][well.y]==0&&flag[well.x][well.y]==0){
                flag[well.x][well.y]=now.k;///标记初始点已经走过了,顺便标记这个点是第几步走的
                well.k=now.k+1;///总步数加1
                Q.push(well);///压进队列
            }
        }
    }
}
int main()
{
    for(int i=0;i<5;i++)
        for(int j=0;j<5;j++)
            cin >> brr[i][j];
    data data;
    data.x=0;
    data.y=0;
    int s=BFS(data);
    cout << s << endl;
    return 0;
}

广搜的特点在于处理方式,并不是同时处理一层数据(只有人脑才能并线处理这么多数据),而是把一个个数据全都存起来(压入队列),一个个处理。想象一下,一个管子,前半部分是“旧数据”,后半部分压入“新数据”。

总结

搜索本身不是问题,难点在于对题目的理解和判断条件的运用,慢慢练,会好的。

第二次总结

搜索是个好东西,只是看似简单而已,这是第二次整理留下了的,我觉得可能还会有下一次。

第三次总结

刷了好多题,觉得搜索越来越不想搜索了,心态炸了!

发布了41 篇原创文章 · 获赞 16 · 访问量 1462

猜你喜欢

转载自blog.csdn.net/weixin_43824551/article/details/88597232