看了这么多题解,关于Java形式的没有一个使用深度优先搜索的(dfs);看到其中有个伙伴的题解提到了,但是考虑到最后一个用例超时,所以也放弃了dfs的方式;
dfs写出来之后其实可以进行剪枝优化,优化后也是能过全部用例的;我这里采用了记忆化搜索的方式,把已经走过的过程记录下来,不在进行递归,这样就能减少非常一大部分的情况了;
关键代码
private static void dfs(int[][] ints, int n, int i, Set<Integer> set, int count,
Map<String, Boolean> alreadyMap) {
if (i == n) {
set.add(count);
return;
}
// 剪枝优化
String key = i + "_" + count;
if (alreadyMap.containsKey(key)) {
return;
}
// 对于第i个元素,可以拿0个或者拿所有
for (int j = 0; j <= ints[i][1]; j++) {
int sum = j * ints[i][0];
dfs(ints, n, i + 1, set, count + sum, alreadyMap);
}
alreadyMap.put(key, true);
}
完整的代码
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
private static void dfs(int[][] ints, int n, int i, Set<Integer> set, int count,
Map<String, Boolean> alreadyMap) {
if (i == n) {
set.add(count);
return;
}
// 剪枝优化
String key = i + "_" + count;
if (alreadyMap.containsKey(key)) {
return;
}
// 对于第i个元素,可以拿0个或者拿所有
for (int j = 0; j <= ints[i][1]; j++) {
int sum = j * ints[i][0];
dfs(ints, n, i + 1, set, count + sum, alreadyMap);
}
alreadyMap.put(key, true);
}
/*
8
69 54 119 85 103 53 155 170
6 6 3 7 6 2 2 4
10
2000 1999 1998 1997 1996 1995 1994 1993 1992 1991
10 10 10 10 10 10 10 10 10 10
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
int n = Integer.parseInt(in.nextLine());
int[][] ints = new int[n][2];
for (int i = 0; i < n; i++) {
ints[i][0] = in.nextInt();
}
for (int i = 0; i < n; i++) {
ints[i][1] = in.nextInt();
}
Set<Integer> set = new HashSet<>();
dfs(ints, n, 0, set, 0, new HashMap<>());
System.out.println(set.size());
// [29, 29, 108, 108, 108, 108, 108, 185]
}
}

京公网安备 11010502036488号