深圳幻海软件技术有限公司 欢迎您!

蓝桥杯——深搜DFS(看完绝对入门DFS)

2023-04-17

大家好,我是璐画同学核心代码:关于dfs参数问题,什么在变化,就把什么设置成参数。voiddfs()//参数用来表示状态 {    if(到达终点状态)    {    

大家好,我是璐画同学


核心代码:

关于dfs参数问题,什么在变化,就把什么设置成参数。

void dfs()//参数用来表示状态  
{  
    if(到达终点状态)  
    {  
        ...//根据题意添加  
        return;  
    }  
    if(越界或者是不合法状态)  
        return;  
    if(特殊状态)//剪枝
        return ;
    for(扩展方式)  
    {  
        if(扩展方式所达到状态合法)  
        {  
            修改操作;//根据题意来添加  
            标记;  
            dfs();  
            (还原标记);  
            //是否还原标记根据题意  
            //如果加上(还原标记)就是 回溯法  
        }  
 
    }  

 先看模板,到这里伙计们肯定不理解到底什么含义,所以我在这里解释下,涉及到深搜的基本提,全是这个套路,现在不理解,先把框架记住,然后用框架去刷几道题就会发现新大陆了

现在,上一道蓝桥杯深搜的考题

题目1

总共有8个不同的字,每个字都代表不同的数,申请一个一维数组a[8]存储这8个不同的数。

a[8]对应有下标index:0至7

所以dfs方法定义为

public static void dfs(int index)

然后设计结束条件,就是index等于8,越界了,代表找够了8个数,尝试进行判断是否构成等式。

  1. if(index == 8) {
  2. int sum = (a[0]*1000+a[1]*100+a[2]*10+a[3]) + (a[4]*1000+a[5]*100+a[6]*10+a[1]);
  3. if(sum == a[4]*10000+a[5]*1000+a[2]*100+a[1]*10+a[7])
  4. System.out.println(a[4]+""+a[5]+""+a[6]+""+a[1]);
  5. return;
  6. }

如果index没有越界,a[]数组没存够8个数,就进行搜索。

因为从0至9搜索,且每个数不能重复,所以每访问一个都需要标记一下,visited[i] 为 0 代表未访问,为 1 代表已访问。

  1. for(int i=0; i<=9; i++) {
  2. if(visited[i] == 0) {// 代表没被访问过,可以访问
  3. visited[i] = 1; // 访问 i, 做标记
  4. a[index] = i; // 往数组里放数
  5. dfs(index+1); // 枚举下一种情况
  6. visited[i] = 0; // 回溯, 清除标记
  7. }
  8. }

通过数学分析,祥字不可能为0,否则无法进位,三字必为1,因为十进制进位只能进1,所以最终搜索代码如下:

  1. for(int i=0; i<=9; i++) {
  2. if(index == 0 && i == 0) {// 祥字不可能为0,否则就无法进位了
  3. continue;
  4. }
  5. if(index == 4 && i != 1) {// 三字必为1,因为十进制进位只能进1
  6. continue;
  7. }
  8. if(visited[i] == 0) {// 代表没被访问过,可以访问
  9. visited[i] = 1; // 访问 i, 做标记
  10. a[index] = i;
  11. dfs(index+1);
  12. visited[i] = 0; // 回溯, 清除标记
  13. }
  14. }

 题目2

有一个大小为N×MN×M N\times MN×M的园子,雨后积起了水。八连通的积水被认为是连接在一起的。请求出园子里总共有多少水洼?八连通指的是下图中相对W的∗部分,‘W’表示积水,’ * '表示没有积水。

 输入

  1. 10 12
  2. W********WW*
  3. *WWW*****WWW
  4. ****WW***WW*
  5. *********WW*
  6. *********W**
  7. **W******W**
  8. *W*W*****WW*
  9. W*W*W*****W*
  10. *W*W******W*
  11. **W*******W*

输出

3

 问题分析

首先定义一个二维数组存储这片下过雨的区域,然后双重for循环遍历一下,每次找到一个 ‘W’ 就记一次数,代表这里有一个水洼,如果继续遍历下去会找到与前面 ‘W’ 相连通的积水,而题上说了只要是相连通的积水就算是一个水洼,因此直接这样遍历是不行的。

为了解决这个重复计算的问题,可以定义一个作为递归的方法,将这个 ‘W’ 的坐标传入,并将这个积水去处,‘W’ 变为 ’ * ’ ,然后以这个坐标为中心,遍历它的八个方向,看看能不能找到下一个 ‘W’ ,找到后向下进行递归,将这个’W’传入本方法,继续进行去除,遍历,直到再也找不到相连通的积水,就表示这一处水洼全部清除了,完美解决重复计算的问题,也解决了两个相连通的积水相互找到对方,陷入无限递归的局面。

 代码实现

  1. import java.util.Scanner;
  2. public class NumberOfPuddles {
  3. static int n, m;
  4. static char[][] field;
  5. public static void main(String[] args) {
  6. Scanner sc = new Scanner(System.in);
  7. n = sc.nextInt();
  8. m = sc.nextInt();
  9. field = new char[n][];
  10. for (int i = 0; i < n; i++) {
  11. field[i] = sc.next().toCharArray();
  12. }
  13. int count = 0;//计数器
  14. for (int i = 0; i < field.length; i++) {
  15. for (int j = 0; j < field[i].length; j++) {
  16. // 枚举整个n*m的园子,每找到一个'W'就代表找到了一个水洼
  17. // 然后用深搜的方式将连通的所有积水全部去除,防止重复计算
  18. if (field[i][j] == 'W') {
  19. count++;
  20. dfs(i, j);
  21. }
  22. }
  23. }
  24. System.out.println(count);
  25. }
  26. private static void dfs(int i, int j) {
  27. field[i][j] = '*';//清除积水
  28. //遍历八个方向找到连通的积水
  29. for (int p = i - 1; p <= i + 1; p++) {
  30. for (int q = j - 1; q <= j + 1; q++) {
  31. if (p >= 0 && p < n && q >= 0 && q < m) {
  32. if (field[p][q] == 'W') {
  33. dfs(p, q);
  34. }
  35. }
  36. }
  37. }
  38. }
  39. }

 到这里,小伙伴们估计还是疑问很大,那么请仔细的对着框架,看这道题,看这个题的代码是不是和框架几乎一模一样啊。

深搜深层分析

题型分类:

写过这些入门题后,我们可以将DFS题分为两大类:


1 . 地图型:这种题型将地图输入,要求完成一定的任务。因为地图的存在。使得题意清楚形象化,容易理清搜索思路。

    AOJ 869-迷宫(遍历地图,四向搜索)
    HDU 1035-Robot Motion(指定方向搜索,迷路(循环)判断)HDU 1035-Robot Motion(指定方向搜索,迷路(循环)判断)
    HDU 1045-Fire Net(check函数,回溯)
 

2 . 数据型:这种题型没有给定地图,一般是一串数字或字母,要求按照一定的任务解题。相对于地图型,这种题型较为抽象,需要在数据中进行搜索。数据以数组的形式存储,那么只要将数组也当作一张图来进行搜索就可以了。

    HDU 1016-Prime Ring Problem(回溯、素数筛)
    HDU 1258-Sum It Up(双重DFS递归,去重技巧)
    HDU 1015-Safecraker(回溯,字符处理)
    HDU 2676-Sudoku(抽象,回溯)

(这里不列举了,全是一个大佬写的文章)
 

最后,每天更新,望大家都得奖!!!

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览44229 人正在系统学习中