问题描述
小M想知道,在不违反规则的前提下,他最多能够击败多少个Boss。
规则如下:
- 每个Boss对应唯一的类型编号。
- 每把武器能够击杀两种编号的boss且只能使用一次。
- 必须按照给定的顺序击杀Boss。
输入拥有的武器数量n 、需要击败的Boss数量m、Boss的顺序boss:长度为m的list、可以使用的武器array:一个长度为n的二维列表,每个元素为 [x, y],可以击败编号为 x 和 y 的Boss。
输出最多击败多少个boss。
使用方法
dfs(枚举选哪个)
算法思路
-
初始化数据结构:
- 使用一个
HashMap(map)来存储每种类型的Boss对应的武器索引列表。键是Boss的类型编号,值是能够击败该Boss的武器索引列表。 - 使用一个布尔数组
vis来标记某个武器是否已经被使用。
- 使用一个
-
构建Boss-武器关系图:
- 遍历二维数组
array,对于每个武器,检查它能够击败的两个Boss类型编号(array[i][0]和array[i][1]),并将对应的武器索引i添加到这两个Boss类型编号在map中的列表里。
- 遍历二维数组
-
深度优先搜索(DFS) :
- 定义一个
dfs函数,它接受当前Boss的索引i作为参数,并返回从当前Boss开始,按照给定顺序最多能击败的Boss数量。 - 如果
i已经等于Boss列表boss的长度,说明已经考虑完所有Boss,返回0。 - 如果当前Boss的类型编号在
map中没有对应的武器列表,说明没有武器能击败这个Boss,返回0。 - 对于当前Boss能够被击败的所有武器,尝试每一种武器,如果该武器(即对应的武器索引)没有被使用过(
vis[tem]为false),则标记为已使用,并递归调用dfs函数处理下一个Boss,同时更新最大击败Boss数量res。
- 定义一个
-
注意事项:
- 每次尝试使用一个武器后,需要将
vis数组中对应的标记恢复,以便回溯到上一个状态,这是深度优先搜索中的“回溯”步骤。 dfs函数中的res = Math.max(dfs(boss, map, i + 1) + 1, res);是关键步骤,它意味着如果使用当前武器能够击败Boss,那么就尝试击败下一个Boss,并更新最大击败Boss数量。
- 每次尝试使用一个武器后,需要将
代码展示
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Main {
static boolean[] vis;
public static int solution(int n, int m, int[] boss, int[][] array) {
// 枚举选哪个
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < array.length; i++) {
if (!map.containsKey(array[i][0])) {
var list = new ArrayList<Integer>();
list.add(i);
map.put(array[i][0], list);
} else {
var list = map.get(array[i][0]);
list.add(i);
map.put(array[i][0], list);
}
if (!map.containsKey(array[i][1])) {
var list = new ArrayList<Integer>();
list.add(i);
map.put(array[i][1], list);
} else {
var list = map.get(array[i][1]);
list.add(i);
map.put(array[i][1], list);
}
}
vis = new boolean[array.length];
return dfs(boss, map, 0);
}
public static int dfs(int[] boss, Map<Integer, List<Integer>> map, int i) {
if (i >= boss.length) {
return 0;
}
if (map.get(boss[i]) == null) {
return 0;
}
int res = 0;
List<Integer> list = map.get(boss[i]);
for (int t = 0; t < list.size(); t++) {
int tem = list.get(t);
if (!vis[tem]) {
vis[tem] = true;
res = Math.max(dfs(boss, map, i + 1) + 1, res);
vis[tem] = false;
}
}
return res;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(
solution(3, 5, new int[] { 1, 2, 3, 4, 5 }, new int[][] { { 1, 2 }, { 3, 2 }, { 4, 5 } }) == 2);
System.out.println(
solution(3, 5, new int[] { 4, 3, 2, 1, 5 }, new int[][] { { 1, 2 }, { 3, 2 }, { 4, 5 } }) == 3);
System.out.println(solution(4, 6, new int[] { 1, 2, 3, 4, 5, 6 },
new int[][] { { 1, 2 }, { 2, 3 }, { 3, 4 }, { 5, 6 } }) == 3);
}
}