华为OD机试 - 欢乐的周末 - 深度优先搜索dfs算法(Java 2023 B卷 200分)

在这里插入图片描述

目录

    • 专栏导读
    • 一、题目描述
    • 二、输入描述
    • 三、输出描述
    • 四、深度优先搜索dfs
    • 五、解题思路
    • 六、Java算法源码
    • 七、效果展示
      • 1、输入
      • 2、输出
      • 3、说明
      • 4、如果修改一下呢?
      • 5、来,TFBOYS,试一下?

华为OD机试 2023B卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

小华和小为是很要好的朋友,他们约定周末一起吃饭。

通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚餐地点不可达),求小华和小为都能到达的聚餐地点有多少个?

二、输入描述

第一行输入m和n,m代表地图的长度,n代表地图的宽度。

第二行开始具体输入地图信息,地图信息包含:

  • 0为通畅的道路
  • 1为障碍物(仅1为障碍物)
  • 2为小华或者小为,地图中必定有且仅有2个(非障碍物)
  • 3为被选中的聚餐地点(非障碍物)

三、输出描述

求小华和小为都能到达的聚餐地点有多少个?

在这里插入图片描述

四、深度优先搜索dfs

在我们遇到的一些问题当中,有些问题我们不能够确切的找出数学模型,即找不出一种直接求解的方法,解决这一类问题,我们一般采用搜索的方法解决。搜索就是用问题的所有可能去试探,按照一定的顺序、规则,不断去试探,直到找到问题的解,试完了也没有找到解,那就是无解,试探时一定要试探完所有的情况(实际上就是穷举);

对于问题的第一个状态,叫初始状态,要求的状态叫目标状态。
搜索就是把规则应用于实始状态,在其产生的状态中,直到得到一个目标状态为止。
产生新的状态的过程叫扩展(由一个状态,应用规则,产生新状态的过程)。

搜索的要点:

  1. 初始状态;
  2. 重复产生新状态;
  3. 检查新状态是否为目标,是结束,否转(2);

如果搜索是以接近起始状态的程序依次扩展状态的,叫宽度优先搜索。

如果扩展是首先扩展新产生的状态,则叫深度优先搜索。

深度优先搜索用一个数组存放产生的所有状态。

  1. 把初始状态放入数组中,设为当前状态;
  2. 扩展当前的状态,产生一个新的状态放入数组中,同时把新产生的状态设为当前状态;
  3. 判断当前状态是否和前面的重复,如果重复则回到上一个状态,产生它的另一状态;
  4. 判断当前状态是否为目标状态,如果是目标,则找到一个解答,结束算法;
  5. 如果数组为空,说明无解。

五、解题思路

求小华和小为都能到达的聚餐地点有多少个?

转成大白话就是,问有几个3可以满足两个2可以同时到达。

  1. 第一行输入地图的长度m,即m行,地图的宽度n,即n列;
  2. 第二行开始具体输入地图信息;
  3. 地图信息初始化;
  4. 利用深度优先搜索dfs算法,获取符合要求的餐馆;
  5. 定义okNum,记录小华和小为都能到达的聚餐地点有多少个;
  6. 如果没有满足条件的,直接输出0;
  7. 如果存在满足条件的餐馆3,则输出都能到达的聚餐地点个数;

六、Java算法源码

package com.guor.od;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class OdTest02 {
    static final int N = 110;
    // 地图信息
    static int[][] arr = new int[N][N];
    static Map<String, Integer> map1 = new HashMap<>();
    static Map<String, Integer> map2 = new HashMap<>();
    static int[] arrX = new int[]{-1, 0, 1, 0};
    static int[] arrY = new int[]{0, 1, 0, -1};
    // 地图的长度
    static int m;
    // 地图的宽度
    static int n;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 地图的长度,即m行
        m = sc.nextInt();
        // 地图的宽度,即n列
        n = sc.nextInt();
        int[] positionArr = new int[4];
        // 地图信息初始化
        for (int i = 0, k = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                arr[i][j] = sc.nextInt();
                if (arr[i][j] == 2) {
                    positionArr[k++] = i;
                    positionArr[k++] = j;
                }
            }
        }

        dfs(positionArr[0], positionArr[1], map1);
        dfs(positionArr[2], positionArr[3], map2);

        // 小华和小为都能到达的聚餐地点有多少个
        int okSum = 0;
        // 如果没有满足条件的,直接输出0
        if (map1.size() == 0 || map2.size() == 0) {
            System.out.println(0);
        } else {
            for (Map.Entry<String, Integer> entry : map1.entrySet()) {
                String key = entry.getKey();
                if (map2.containsKey(key)) {
                    okSum++;
                }
            }
            System.out.println(okSum);
        }
    }

    /**
     * 利用深度优先搜索dfs算法,获取敌人数小于K的区域数量
     */
    public static void dfs(int x, int y, Map<String, Integer> map) {
        if (arr[x][y] == 3) {
            String key = get(x, y);
            map.put(key, map.getOrDefault(key, 0) + 1);
            return;
        }
        int k = arr[x][y];
        arr[x][y] = -1;
        for (int i = 0; i < 4; i++) {
            int a = arrX[i] + x, b = arrY[i] + y;
            if (a >= 0 && a < m && b >= 0 && b < n && arr[a][b] != 1 && arr[a][b] != -1 && !map.containsKey(get(a, b))) {
                dfs(a, b, map);
            }
        }
        arr[x][y] = k;
    }

    public static String get(int x, int y) {
        return String.valueOf(x) + "@" + String.valueOf(y);
    }
}

七、效果展示

1、输入

6 5
2 1 0 3 0
0 1 2 1 3
0 3 0 0 0
0 0 0 0 1
0 0 3 0 1
0 0 0 1 3

2、输出

4

3、说明

6行5列。

  • 0为通畅的道路
  • 1为障碍物(仅1为障碍物)
  • 2为小华或者小为,地图中必定有且仅有2个(非障碍物)
  • 3为被选中的聚餐地点(非障碍物)

求小华和小为都能到达的聚餐地点有多少个?

转成大白话就是,问有几个3可以满足两个2可以同时到达。

在这里插入图片描述

4、如果修改一下呢?

卫生不达标,将通往右上角的餐馆道路锁死。

6 5
2 1 1 3 0
0 1 2 1 3
0 3 0 0 1
0 0 0 0 1
0 0 3 0 1
0 0 0 1 3

在这里插入图片描述
右眼可见,会输出2。

在这里插入图片描述

5、来,TFBOYS,试一下?


下一篇:华为OD机试真题 Java 实现【路灯照明问题】【2022Q4 100分】,感谢fly晨发现这个问题,并提供更优质的算法

本文收录于,华为OD机试(JAVA)真题(A卷+B卷)

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

你可能感兴趣的:(搬砖工逆袭Java架构师,算法,华为od,深度优先,七日集训,学习,送书)