蓝桥杯中的BFS(含算法分析,蓝桥杯真题,解题思路和代码)

BFS(宽度优先搜索)

1.定义:

  • 从初始状态S开始,利用规则,生成所有可能的状态,构成树的下一层节点,检查是否出现目标状态G; 若未出现,就对该层所有状态节点,分别顺序利用规则,生成再下一层的所有状态节点,对这一层的所有状态节点检查是否出现目标状态G ;  若未出现,继续按上面思想生成再下一层的所有状态节点,这样一层一层往下展开,直到出现目标状态为止。

  • 如图:

  • 值得注意的是BFS是依靠队列来进行实现,正如DFS是依靠栈,这个思想有助于我们理解算法。

  • 算法分析:

  • 最短路径问题:在图或网格中,求从起点到终点的最短路径,要求各边权重相同 。如在迷宫中找从入口到出口的最少步数路径,因为 BFS 是按层搜索,先访问到的节点离起点更近,满足条件时能找到最短路径。
  • 层次遍历问题:对树或图进行层次遍历,像二叉树的按层遍历。通过 BFS 可依次访问每一层节点。
  • 状态转移问题:状态之间存在多种转移方式,要找从初始状态到目标状态的最少转移次数等,可把状态看成节点,转移关系看成边,用 BFS 求解。

蓝桥杯真题:

青蛙跳杯子

题目描述

XX 星球的流行宠物是青蛙,一般有两种颜色:白色和黑色。

XX 星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。

如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。

∗WWWBBB

其中,W字母表示白色青蛙,B表示黑色青蛙,∗ 表示空杯子。

XX 星的青蛙很有些癖好,它们只做 3 个动作之一:

  1. 跳到相邻的空杯子里。

  2. 隔着 1 只其它的青蛙(随便什么颜色)跳到空杯子里。

  3. 隔着 2 只其它的青蛙(随便什么颜色)跳到空杯子里。

对于上图的局面,只要 1 步,就可跳成下图局面:

WWW∗BBB

本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。

输入描述

输入为 2 行,2 个串,表示初始局面和目标局面。我们约定,输入的串的长度不超过 15。

输出描述

输出要求为一个整数,表示至少需要多少步的青蛙跳。

输入输出样例

示例

输入

*WWBB
WWBB*

输出

2

 此处的问题为至少需要几步,才能跳成另一个目标局面,即为最短路径问题,以示例为例,我们可以把*WWBB作为第一层,此时步数为0,而第一层的每有多少下一个状态呢?我们可以发现它有5个字符,如果都是青蛙,那么每一只青蛙所走的下一步都是下一层的一部分,而一只青蛙可以最多有六中走法,于是我们就发现了每一层之间的联系,即将每一只青蛙可能的下一步所形成的状态之和为下一层。接下只要判断能否移动即可。

代码实现:

package qingwa;
import java.util.*;
public class Main {
    // 用字符串来表示每次都状态
    static String first;
    static String end;
    static int step=0;//用来表示步数
    static Queue <String>q=new <String>LinkedList();
    static int arr[]= {-3,-2,-1,1,2,3};
    static HashSet <String>set=new <String>HashSet();
    public static void bfs() {
        while(!q.isEmpty()) {
            int size=q.size();
            step++;//此处是遍历了一层加一步
            for(int i=0;i<size;i++) {
                String t=q.poll();
                if(t.equals(end)) {
                    System.out.print(step-1);//减去一是因为从初状态加一,这会使step多算一步
                    return;
                }
                for(int k=0;k<t.length();k++) {
                    char t1=t.charAt(k);//表示所在位置的字符
                    if(t1!='*') {
                        for(int j=0;j<arr.length;j++) {
                            if((k+arr[j])>=0&&(k+arr[j])
        <t.length()&&t.charAt(k+arr[j])=='*') {
                                StringBuffer a=new StringBuffer(t);
                                a.setCharAt(k, '*');
                                a.setCharAt(k+arr[j], t1);//交换位置
                                String t2=a.toString();//此时得到了下一个状态
                                if(!set.contains(t2)) {
                                    set.add(t2);
                                    q.add(t2);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    public static void main(String arg[]) {
        Scanner sc=new Scanner(System.in);
        first=sc.nextLine();
        end=sc.nextLine();
        q.add(first);
        set.add(first);
        bfs();
    }
}

代码参考了蓝桥杯上的题解,如有雷同,不是偶然

总结:BFS最常考的情况就是最短路径问题,而BFS的难处在于如何确定每一层的状态,我们不妨从头推起,开始必然是一个状态,而接下来我们要看初始状态有多少个下一步,从而作为依据来不断进行下一步的分析,值得注意的是我们需要一个容器(数组或者哈希表)来记录我们走过的情况避免重复。

我的dfs的文章:蓝桥杯中的DFS(含算法分析,蓝桥杯真题,解题思路和代码)-优快云博客


题目链接(可以测试一下自己): 

1.青蛙跳杯子 - 蓝桥云课https://www.lanqiao.cn/problems/102/learning/?page=1&first_category_id=1&second_category_id=3&tags=%E7%9C%81%E8%B5%9B,BFS&tag_relation=intersection

还有几道蓝桥杯的dfs可以练手:

2.卡片换位 - 蓝桥云课https://www.lanqiao.cn/problems/125/learning/?page=1&first_category_id=1&second_category_id=3&tags=%E7%9C%81%E8%B5%9B,BFS&tag_relation=intersection3.扫雷 - 蓝桥云课https://www.lanqiao.cn/problems/549/learning/?page=1&first_category_id=1&second_category_id=3&tags=%E7%9C%81%E8%B5%9B,BFS&tag_relation=intersection

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值