目录
- 专栏导读
- 一、题目描述
- 二、输入描述
- 三、输出描述
- 四、深度优先搜索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
在我们遇到的一些问题当中,有些问题我们不能够确切的找出数学模型,即找不出一种直接求解的方法,解决这一类问题,我们一般采用搜索的方法解决。搜索就是用问题的所有可能去试探,按照一定的顺序、规则,不断去试探,直到找到问题的解,试完了也没有找到解,那就是无解,试探时一定要试探完所有的情况(实际上就是穷举);
对于问题的第一个状态,叫初始状态,要求的状态叫目标状态。
搜索就是把规则应用于实始状态,在其产生的状态中,直到得到一个目标状态为止。
产生新的状态的过程叫扩展(由一个状态,应用规则,产生新状态的过程)。
搜索的要点:
- 初始状态;
- 重复产生新状态;
- 检查新状态是否为目标,是结束,否转(2);
如果搜索是以接近起始状态的程序依次扩展状态的,叫宽度优先搜索。
如果扩展是首先扩展新产生的状态,则叫深度优先搜索。
深度优先搜索用一个数组存放产生的所有状态。
- 把初始状态放入数组中,设为当前状态;
- 扩展当前的状态,产生一个新的状态放入数组中,同时把新产生的状态设为当前状态;
- 判断当前状态是否和前面的重复,如果重复则回到上一个状态,产生它的另一状态;
- 判断当前状态是否为目标状态,如果是目标,则找到一个解答,结束算法;
- 如果数组为空,说明无解。
五、解题思路
求小华和小为都能到达的聚餐地点有多少个?
转成大白话就是,问有几个3可以满足两个2可以同时到达。
- 第一行输入地图的长度m,即m行,地图的宽度n,即n列;
- 第二行开始具体输入地图信息;
- 地图信息初始化;
- 利用深度优先搜索dfs算法,获取符合要求的餐馆;
- 定义okNum,记录小华和小为都能到达的聚餐地点有多少个;
- 如果没有满足条件的,直接输出0;
- 如果存在满足条件的餐馆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在线答疑。