解题代码:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int num;
static int[] sticks;
static boolean[] vists;
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
int maxLen;
int sumLen;
while ((num = stdin.nextInt()) != 0) {
sticks = new int[num];
vists = new boolean[num];
sumLen = 0;
for (int i = 0; i < num; i++) {
sticks[i] = stdin.nextInt();
sumLen += sticks[i];
}
Arrays.sort(sticks);
maxLen = sticks[num - 1];
boolean flag = false;
for (int l = maxLen; l <= sumLen - maxLen; l++) { //剪枝1,若能在[maxlen,sumlen-InitLen]找到最短的l,该l必也是[maxlen,sumlen]的最短
//剪枝2,InitLen必是sumlen的约数
if ((sumLen%l == 0)&&dfs(0, l, num - 1, 0)) {
System.out.println(l);
flag = true;
}
}
if(!flag) {
System.out.println(sumLen);
}
}
}
private static boolean dfs(int len, int l,
int s, int n) {
if (n == num) {
return true;
}
int sample = -1;
for (int i = s; i >= 0; i--) {
if(vists[i] || sticks[i]==sample) { //剪枝3,等长的木棒只搜索一次
continue;
}
vists[i] = true;
if (len + sticks[i] == l) {
if (dfs(0, l, num - 1, n + 1)) {
return true;
} else {
sample = sticks[i];
}
} else if (len + sticks[i] < l) {
if (dfs(len + sticks[i], l, i, n+1)) {
return true;
} else {
sample = sticks[i];
}
}
vists[i] = false;
if (len == 0) {//剪枝4,构建新棒时,对于新棒的第一根棒子,在搜索完所有棒子后都无法组合
//则说明该棒子无法在当前组合方式下组合,不用往下搜索(往下搜索会令该棒子被舍弃),直接返回上一层
break;
}
}
return false;
}
}
DFS + 剪枝