不会做借鉴了一下大佬的题解…
题解
先用DFS中枚举要去掉的砝码和已经选择过的砝码,然后用01背包记录称得砝码的最大值。
import java.util.*;
public class Main {
private static int n, m, re = 0;
private static int arr[], dp[], f[];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
m = scan.nextInt();
arr = new int[n + 1];
for (int i = 0; i < n; i++) {
arr[i] = scan.nextInt();
}
f = new int[20021];//记录砝码有没有被去掉 有被选中去掉为1,否则为0
DFS(0, 0);
System.out.println(re);
}
public static void DFS(int cur, int now) {
// cur:当前已经选择过的砝码 now:当前已选择放弃的砝码
if (now > m) {
return;
}
if (cur == n) {
if (now == m) {
Cal();
}
return;
}
// 不放弃当前砝码
DFS(cur + 1, now);
f[cur] = 1;
// 放弃当前砝码
DFS(cur + 1, now + 1);
f[cur] = 0;
}
public static void Cal() {
dp = new int[20021];//可能会调用多次,需要初始化
dp[0] = 1;//没选择任何砝码,结果只有1种
int tot = 0, ans = 0;
for (int i = 0; i < n; i++) {
if (f[i] == 1)//已经选择去掉的砝码就跳过
continue;
for (int j = tot; j >= 0; j--) {//倒着算保证每个砝码只选一次
if (dp[j] == 1 && dp[j + arr[i]] == 0) {
//这边的+,指的是加上新砝码进行称重
dp[j + arr[i]] = 1;
ans++;
}
}
tot += arr[i];
}
re = Math.max(ans, re);
}
}
(小菜鸟第一次发题解,如果有思路不清晰的地方,欢迎指正