dfs和bfs算法模版

dfs和bfs算法模版

  • dfs
    • 算法思路模版
    • 模版题
  • bfs
    • 算法思路模版
    • 模版题

dfs

dfs的话,其实可以看做是一个递归树
利用栈或者标记数组进行回溯

算法思路模版

int(void) dfs(int x)
{
	//递归结束的判断条件
	//标记位置
	//dfs(int x)
	//恢复现场(有些题可不用,比如迷宫问题)
}

模版题

dfs和bfs算法模版_第1张图片dfs和bfs算法模版_第2张图片

此模版题,我写了2种dfs的算法,
一种是枚举四个方向的位置,然后再dfs
一种是直接dfs四个方向

/*#include
#include
#include

using namespace std;

const int N = 25;
char g[N][N];
int st[N][N];

//(1, 0)  (-1, 0) (0, -1) (0, 1)
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, -1, 1};

int n, m;
int ans;


//版本一: 枚举当前位置的四个方向,然后dfs
int dfs1(int x, int y)
{
    int res = 1;
    
    //标记当前位置
    st[x][y] = 1;
    
   // 枚举当前位置的四个方向
    
    for(int i = 0; i < 4; i++)
    {
        int a = x + dx[i];
        int b = y + dy[i];
        
        //1.判断枚举的位置是否合法
        //2.如果合法,标记这个位置,然后继续dfs
        
        //判断是否越界
        if(a < 0 || a >= m || b < 0 || b >= n)  continue;
     
        //判断是否是可走
        if(g[a][b] == '#')  continue;
        
          //判断是否遍历过
        if(st[a][b])   continue;
        
        //当前枚举的这个位置合法
        
        //标记枚举的这个位置
        st[a][b] = 1;
        
        //继续dfs,枚举的位置(a, b)
        res += dfs1(a, b);
    }
 

    return res;
}


//版本二:直接递归四个方向
void  dfs2(int x, int y)
{
    //递归结束的条件 (return)
    if(x < 0 || x >= m || y < 0 || y >= n)  return;
    if(st[x][y])    return;
    if(g[x][y] == '#')  return;
    
    ans++;
    //不要忘记,标记当前位置
    st[x][y] = 1;
    
    dfs2(x + 1, y);
    dfs2(x - 1, y);
    dfs2(x, y + 1);
    dfs2(x, y - 1);
    
    //走格子,不需要恢复现场
}


int main()
{
 
    while(cin >> n >> m, n || m)
    {
        for(int i = 0; i < m; i++) scanf("%s",g[i]);
        
        //有多组数据,注意ans要初始化
        
        ans = 0;
        
        //找到起点
        int x, y;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++)
                if(g[i][j] == '@')
                    x = i, y = j;
                    
        
        
        //这里注意:
        //输入多个数据集合,每个数据集合的,标记数组都要进行初始化
        memset(st, 0, sizeof st);
        
        //cout << dfs1(x, y) << endl;
        
        
        //版本二:
        dfs2(x, y);
        cout << ans << endl;
        
    }
    
    return 0;
}

*/

bfs

求最小值,一般采用bfs算法,而不是dfs算法

算法思路模版

/*
    bfs: 一般模板
    
    思想(类似树的层次遍历,取出队列的头部元素,然后将与这个头部元素
    相关的,放到队尾里去)
    
    void bfs()
{
    queue q;//一般用stl库中的queue来实现队列比较方便
    q.push(起点S);//将初始状态入队
    //标记初始状态已入队。
    while(!q.empty())//队列不为空就执行入队出队操作
    {
        top = q.front();//取出队首
        q.pop();//队首出队
        for (枚举所有可扩展的状态)
        {
            if (check())//状态合法
            {
                q.push(temp);//状态入队
                //标记成已入队。
            }

        }
    }

*/

模版题

dfs和bfs算法模版_第3张图片
dfs和bfs算法模版_第4张图片

//bfs 使用队列,  dfs 使用栈
#include
#include
#include
#include
#include

using namespace std;

const int N = 210;
char map[N][N];
int  dist[N][N];  //标记数组,也用来记录距离
int T;
int R, C;

#define x first
#define y second

//用pair类型,来存储坐标
typedef pair<int, int> PII;



int bfs(PII start, PII end)
{
    
    queue<PII> q;
    
    //标记数组值初始化为-1,走到这步为0, 从这步走到下一步就加1,算距离
    memset(dist, -1, sizeof dist);
    
    //标记起始点
    dist[start.x][start.y] = 0;
    
    //起点入队
    q.push(start);
    
    //上下左右四个方向,用偏移量
    int dx[4] = {-1, 1, 0, 0};
    int dy[4] = {0, 0, -1, 1};
    
    while(!q.empty())
    {
        //取出队列的头部元素
        auto top = q.front();
        q.pop();  //出队列
        
        //利用偏移量求出四个方向
        for(int i = 0; i < 4; i++)
        {
            int x = top.x + dx[i];
            int y = top.y + dy[i];
            
            //判断结束循环的情况
            //是障碍物
            if(map[x][y] == '#')
            {
                continue;
            }
            
            //判断是否超过边界
            //这里边界要取等,因为数组下标从0开始的
            if(x >= R || x < 0 || y >= C || y < 0)
            {
                continue;
            }
            
            //判断是否遍历过
            if(dist[x][y] != -1)
            {
                continue;
            }
            
            //从上步走到下步距离加1
            dist[x][y] = dist[top.x][top.y] + 1;
            
            if( end == make_pair(x, y))
            {
                return dist[x][y];    
            }
            
            //相关的元素,放进队列中
            q.push({x, y});
            
        }
        
    }
    
    return -1;
}

int main()
{
    cin >> T;
    
    while(T--)
    {
        cin >> R >> C;
        
        // 初始化迷宫 (字符数组,可以以字符串的方式输入)
        for(int i = 0; i < R; i++)
        {
            cin >> map[i];
        }
        
        //记录起点和终点的位置
        PII start, end;
        
        for(int i = 0; i < R; i++)
        {
            for(int j = 0; j < C; j++)
            {
                if(map[i][j] == 'S')
                {
                    start = {i, j};
                }
                if(map[i][j] == 'E')
                {
                    end = {i, j};
                }
            }
        }
        
        
        int distance = bfs(start, end);
        
        if(distance == -1)
        {
            cout << "oop!" << endl;
        }
        else
        {
            cout << distance << endl;   
        }
    }
    return 0;
}

你可能感兴趣的:(算法模板总结,深度优先,算法,宽度优先)