一种方法是直接搜索,搜索子集树,但太慢
import java.util.Arrays;
/**
* 直接搜索求解,慢
* @author Administrator
*
*/
public class SplitArray {
static final int MAX = 5;
static int[] array = { 2, 5, 2, 1, 4 };
static int sum_2;
static {
for (int i = 0; i < MAX; i++)
sum_2 += array[i];
sum_2 /= 2;
}
static int best = 100000;
static int cv;
static int[] result = new int[MAX];
static int[] helper = new int[MAX];
static void back(int t) {
if (t == MAX) {
if (Math.abs(cv - sum_2) < best) {
best = Math.abs(cv-sum_2);
System.arraycopy(helper, 0, result, 0, helper.length);
}
return;
}
if (cv <= sum_2) { // 大于就没必要再加了,加了只能更大
helper[t] = 1;
cv += array[t];
back(t + 1);
helper[t] = 0;
cv -= array[t];
back(t + 1);
}
}
public static void main(String args[]) {
back(0);
for (int i = 0; i < MAX; i++) {
if (result[i] == 1)
System.out.print(array[i]+" ");
}
}
}
第二种方法就是利用背包思想,包大为 sum(array)/2,然后向包中装物品,使 其中大(不过不确定这种方法的正确性,因为此时规定 装入的东西不得大于 sum/2)但事实是
可以大于sum/2
import java.util.Arrays;
public class SplitArray2 {
/*
* 将数组分成两个和最接近的数组,分解的数组的长度不定 给定一个数组,[2,5,2,1,4] sum_2 =
* sum(array)/2,也就是用sum_2的体积去装array 中的物品,使其最大
*/
static final int SIZE = 20;
static int[][] result = new int[SIZE][SIZE];
static void execute(int[] array, int len) {
int sum_2 = 0;
for (int i = 1; i < len; i++)
sum_2 += array[i];
sum_2 >>= 1;
for (int i = 1; i < len; i++) {
for(int j=0;j<=sum_2;j++){
if(j>=array[i]){
result[i][j] = Math.max(result[i-1][j],result[i-1][j-array[i]]+array[i]);
}else
result[i][j] = result[i-1][j];
}
}
int j = sum_2;
for(int i=len-1;i>0;i--){
if(result[i][j]>result[i-1][j]){ // 找到第一个接近 sum/2 的,然后与 它上面的比较,如果大于,则代表当前 i 被选中
System.out.println(array[i]);
j -= array[i];
}
}
}
public static void main(String args[]) {
int[] array = { 0, 2, 5, 2, 1, 4 }; // 元素从1 开始
execute(array,array.length);
}
}