BFS和DFS

BFS

其实广度优先搜索就是利用了广度优先遍历的一种搜索算法。我个人总结的该算法包含以下几个关键点,掌握了这几个点,该算法也就掌握的很好了。下面也基本上是围绕这几个关键点展开的。

1.状态

2.状态转移方式 

3.有效状态

4.队列

5.标记

迷宫问题

链接:http://poj.org/problem?id=3984

本题也是一个走迷宫的问题,但是本题和之前的几道题之间的差距就在于本题问你是如何走得,也就时你走迷宫的具体路径,主体思想跟之前的几道题没有变依然是bfs类的问题,但是重点是如何储存走过的点,以及如何输出。

记录输入输出的思想就是要从终点开始往回找点,用另外的结构体数组储存一下,然后输出就可以了,但是如何往回找呢?往回找就看你是如何储存的,先申请结构体数组。用要压入点的位置pre[tmp2.x][tmp2.y].x来记录前一个数组横坐标的位置,pre[tmp2.x][tmp2.y].y来记录另外一个数字纵坐标的位置。

pre[tmp2.x][tmp2.y].x = tmp1.x;

pre[tmp2.x][tmp2.y].y = tmp1.y; 

#include<stdio.h>
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int maze[6][6];
int vis[6][6];
 
struct Point{
     int x, y;
}tmp1, tmp2;
Point pre[10][10];
int mt[4][2] = {1,0,-1,0,0,1,0,-1};
queue<Point>q;
Point ans[30];
int main(){
    int i, j;
    while(~scanf("%d %d %d %d %d", &maze[0][0], &maze[0][1], &maze[0][2], &maze[0][3],&maze[0][4],&maze[0][5])){
        for(i = 1; i < 5; i++){
            for(j = 0; j < 5; j++){
                scanf("%d", &maze[i][j]);
            }
        }
        while(!q.empty()){
            q.pop();
        }
        memset(vis, 0, sizeof(vis));
        tmp1.x = 0;
        tmp1.y = 0;
        vis[0][0] = 1;
        q.push(tmp1);
        while(!q.empty()){
            tmp1 = q.front();
            q.pop();
            for(i = 0; i < 4; i++){
                tmp2.x = tmp1.x + mt[i][0];
                tmp2.y = tmp1.y + mt[i][1];
                if(tmp2.x >= 0 && tmp2.x < 5 && tmp2.y >= 0 && tmp2.y < 5 && !vis[tmp2.x][tmp2.y] && maze[tmp2.x][tmp2.y] == 0){
                    //约束条件
                    vis[tmp2.x][tmp2.y] = vis[tmp1.x][tmp1.y] + 1;
                    q.push(tmp2);
                    pre[tmp2.x][tmp2.y].x = tmp1.x;//保存前一个位置的横坐标
                    pre[tmp2.x][tmp2.y].y = tmp1.y;//保存前一个位置的纵坐标
 
                }
            }
            if(vis[4][4])break;
        }
        //cout<<vis[4][4]<<endl;
        int lastx = 4, lasty = 4;//终点的位置
        int x, y, num = 0;
        while(lastx || lasty){//如果lastx, lassty,如果全为零的话就停止
            ans[num].x = lastx;//ans 来记录一下
            ans[num++].y = lasty;
 
            x = lastx;
            y = lasty;
            lastx = pre[x][y].x;//读取下一个,也就是之前保存的前一个
            lasty = pre[x][y].y;
 
        }
        //cout<<num<<endl;
        printf("(0, 0)\n");
        for(i = num-1; i >= 0; i--){//逆序输出
            printf("(%d, %d)\n", ans[i].x, ans[i].y);
        }
 
    }
return 0;
}

DFS

dfs基于递归思想,递归思想就是把一个事拆分成若干见相同的小事共同组合完成

理解深度优先算法的关键在于解决“当下该如何做”。至于下一步应该如何做,和当下应该如何做是一样的,对!就是用递归!自己调用自己!

关键:

void dfs(int step)
{
    判断边界,如果到了边界当然直接返回啦
    尝试每一种可能结果for(i=0;i<n;i++)
    {
        处理当前步
        继续下一步dfs(step + 1)
    }
    返回
}

例题八皇后问题

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

#include<iostream>  
    #include<cstdio>  
    #include<cstdlib>  
    using namespace std;  
    int hang[11], n=8;  
    int a[10][10] = { 0 };  
    int t = 1;  
    void print()  
    {  
        printf("No. %d\n", t++);  
        for (int i = 1; i <= 8; i++)  
        {  
            for (int j = 1; j <= 8; j++)  
            {  
                printf("%d ", a[j][i]);  
            }  
            printf("\n");  
        }  
    }  
    bool judge(int num)  
    {  
        for (int i = 1; i < num; i++)  
            if (hang[num] == hang[i] || abs(hang[i] - hang[num]) == num - i)  
                //判断列和对角线  
                return 0;  
        return 1;  
    }  

    void dfs(int num)  
    {  
        if (num >= 9){  
            print();  
        }  
        for (int i = 1; i <= 8; i++)  
        {  
            hang[num] = i;  
            if (a[num][i]!=1&&judge(num))  
            {  
                a[num][i] = 1;  
                dfs(num + 1);  
                a[num][i] = 0;  
            }  

        }  

    }  

    int main()  
    {  
        //freopen("1.txt", "w", stdout);  
            dfs(1);  
        return 0;  
    }  

输出部分截图。

 

### BFS DFS 的特点及应用场景 #### 特点对比 广度优先搜索 (BFS) 深度优先搜索 (DFS) 是图树结构中最常用的两种遍历方法。以下是两者的具体特点: 1. **探索顺序** - 广度优先搜索 (BFS) 按照层次依次访问节点,即先访问当前层的所有节点再进入下一层[^3]。 - 深度优先搜索 (DFS) 则沿着一条路径尽可能深入地访问节点直到无法继续,然后再回溯并尝试其他分支[^1]。 2. **数据结构支持** - BFS 使用队列作为辅助数据结构来存储待访问的节点,确保按先进先出的原则处理节点[^4]。 - DFS 可通过递归调用栈或者显式的栈实现,利用后进先出的方式管理未完成的子树遍历操作[^2]。 3. **时间复杂度与空间需求** - 时间复杂度方面两者均为 O(V+E),其中 V 表示顶点数量 E 边的数量。 - 空间消耗上,由于 BFS 需要维护整个宽度方向上的节点列表,在某些极端情况下可能占用较多内存;相比之下,DFS 更节省空间因为它仅需保留从根到叶的一条路径信息即可。 #### 应用场景分析 1. **寻找最短路径问题** - 如果目标是最少步数到达某个特定位置,则应选用 BFS 方法。这是因为当首次抵达终点时所经历的距离必然最小——这是由其逐级扩展特性决定的。 2. **全解枚举任务** - 对于需要穷尽所有可能性的情况,例如生成排列组合等问题,推荐采用 DFS 技术。它能够有效减少中间状态保存量从而提高效率。 3. **拓扑排序或其他依赖关系解析场合** - 当存在明确的方向性先后次序约束条件下构建解决方案时,这两种技术都可以发挥作用。不过通常来说,基于堆栈特性的 DFS 实现起来更为直观简便一些。 ```python from collections import deque def bfs(graph, start_node): visited = set() queue = deque([start_node]) while queue: node = queue.popleft() if node not in visited: print(node) visited.add(node) neighbors = graph[node] for neighbor in neighbors: if neighbor not in visited: queue.append(neighbor) def dfs_recursive(graph, current_node, visited=None): if visited is None: visited = set() if current_node not in visited: print(current_node) visited.add(current_node) for next_node in graph[current_node]: if next_node not in visited: dfs_recursive(graph, next_node, visited) graph_example = { 'A': ['B', 'C'], 'B': ['D', 'E'], 'C': ['F'], 'D': [], 'E': ['F'], 'F': [] } print("BFS Traversal:") bfs(graph_example, 'A') print("\nDFS Recursive Traversal:") dfs_recursive(graph_example, 'A') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值