BFS广搜和DFS深搜

基础理解就不总结了,

理解了自然就会写,多写几次就不会忘记了。

那么就推荐一篇:https://zhuanlan.zhihu.com/p/24986203

我就总结说说技巧吧。

首先呢,我个人还是更喜欢bfs的,好写好理解,而且联系到有使用容器来优化的一些算法,更常用吧。

先抬一手习惯代码:

复制代码
#define N 2021
#define mt(x) memset(x,0,sizeof x)
char mp[N][N];
int vis[N][N][2];
int f[]={1,0,-1,0};
int g[]={0,1,0,-1};
初始化定义
复制代码

其中f和g两个方向数组,这只写了上下左右四个方向,对应的还有左上左下右上右下也是一个写法,建议尽量以顺逆时针方向转着写。

当然亦可以直接二维方向数组。

经典路径回溯,就多一个二维数组结构体(两个坐标成员变量),定义find[i][k]的两个表示i,k坐标来自于其成员变量的搜索。

然后用递归遍历输出

比如:

复制代码
void PR(int x,int y)
{
    if(x||y)PR(find[x][y].x,find[x][y].y);
    printf("%d %d\n",x,y);
} 
路径回溯
复制代码

(这是以0,0坐标为原点的回溯,其他原点改一下if判断即可)

举个经典例题吧:http://120.78.128.11/Problem.jsp?pid=1281

再贴个精简AC代码:

复制代码
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int a,b,c,X,Y,Z;
struct iii
{
    int x,y,z;
    bool operator <(const iii &p)const
    {
        return p.z<z;
    }
}mp[109][109];
priority_queue<iii>q;
void add(int m,int n,int p)
{
    if(mp[m][n].z)return ;
    q.push({m,n,Z+1});
    mp[m][n].x=X;
    mp[m][n].y=Y;
    mp[m][n].z=p;
}
void PR(int x,int y)
{
    if(x||y)PR(mp[x][y].x,mp[x][y].y);
    int p=mp[x][y].z;
    if(!p)printf("%d\n",Z);
    else if(p<3)printf("FILL(%d)\n",p);
    else if(p<5)printf("DROP(%d)\n",p-2);
    else puts(p-5?"POUR(1,2)":"POUR(2,1)");
}
void BFS()
{
    memset(mp,0,sizeof(mp));
    q.push({0,0,0});
    while(q.size())
    {
        X=q.top().x;Y=q.top().y;Z=q.top().z;
        q.pop();
        if(X==c||Y==c)
        {
            while(q.size())q.pop();
            PR(X,Y);
            return ;
        }
        if(!X)
        {
            if(!Y)add(a,0,1),add(0,b,2);
            else
            {
                a>=b?add(Y,0,5):Y>=a?add(a,Y-a,5):add(Y,0,5);
                add(a,Y,1);
            }
        }
        else
        {
            if(!Y)
            {
                a>=b?X>=b?add(X-b,b,6):add(0,X,6):add(0,X,6);
                add(X,b,2);
            }
            else
            {
                if(X!=a)Y>=a-X?add(a,Y+X-a,5):add(X+Y,0,5);
                if(Y!=b)X>=b-Y?add(X+Y-b,b,6):add(0,X+Y,6);
                add(0,Y,3);add(X,0,4);
            }
        }
    }
    puts("impossible");
}
int main()
{
    while(~scanf("%d %d %d",&a,&b,&c))BFS();
    return 0;
} 
看不懂别怪我
复制代码

 

还有一类是经典树棍搜索,往往带有范围,所以是深搜题

比如给定一个数的倍数只能有x个数字组成,位数不超过n位,然后要求找去最小值这种,基本dfs注意搜索顺序就能写了

像这个题:http://120.78.128.11/Problem.jsp?pid=1278

 

其他想到了再补吧。

posted @   Renhr  阅读(67)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示