如何在具有相同数量的元素和最接近的两个子集中划分一组数字?

时间:2018-03-24 19:58:47

标签: algorithm math

给定一组n个数,n个偶数,我如何得到两个n / 2个数的子集,每个子​​集中数字的总和尽可能接近?

实施例: 设定= {1.6,4.0,0.7,2.9,5.0,3.1,5.0,1.0,0.6,5.0},总和28.9

子集可以是: {5.0,5.0,2.9,1.0,0.6},总和14.5和 {5.0,4.0,3.1,1.6,0.7},总和14.4

我需要一个算法,伪代码很好。

谢谢!

2 个答案:

答案 0 :(得分:0)

我看待它的方式是:有两个列表,空白。 a = [],b = [] 对于x中的每个元素(数字列表),将其附加到最需要它的那个元素,也就是说,其总和小于另一个元素。

x=[1.6, 4.0, 0.7, 2.9, 5.0, 3.1, 5.0, 1.0, 0.6, 5.0]
x.sort()
x.reverse()
print(x)
#[5.0, 5.0, 5.0, 4.0, 3.1, 2.9, 1.6, 1.0, 0.7, 0.6]
b=[];c=[]
for i in a:
    if sum(b) <= sum(c):
        b.append(i)
    else:
        c.append(i)
print(sum(b))
print(sum(c))

#Hope this helps!

编辑: 如果我们希望这些集合具有相同的大小,那么这可能会成为一个问题。使用组合学将需要很长时间,但我认为没有其他选择。然后,我的知识有限。所以这里是:
给定一组22,找到一组11,总和为22的一半,或尽可能接近。如果它尽可能接近,请查看开关元件是否会产生更好的结果。但这与组合学一样低效。

这是一个非常难的问题。甚至维基百科都承认了这一点。 :-D: - (

抱歉,我无法提供更多帮助。

答案 1 :(得分:0)

我找到了解决方案。 这是java实现:

package javaapplication;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;


public class JavaApplication {

    private static DecimalFormat df = new DecimalFormat(".#");
    private static double totalCuadroIzquierdo = 0;
    private static double totalCuadroDerecho = 0;
    private static ArrayList<Double> cuadroIzquierdo;
    private static ArrayList<Double> cuadroDerecho;

    public static void main(String[] args) {

        Double[] vectorTodos = {
            //100.0,99.0,98.0,89.0,76.0,60.0,56.0,45.0,43.0,32.0, 5.0, 5.0, 5.0, 4.1, 3.9, 3.1, 2.4, 1.7, 1.0, 0.6 
            //100.0,99.0,98.0,89.0,76.0,60.0,56.0,45.0,43.0,32.0, 5.0, 4.1, 3.9, 3.1, 2.4, 1.7, 1.0, 0.6 
            //99.0,89.0,76.0,60.0,56.0,45.0,43.0,32.0, 5.0, 4.1, 3.9, 3.1, 2.4, 1.7, 1.0, 0.6 
            99.0,60.0,56.0,45.0,43.0,32.0
            //5.0, 4.1//, 3.9, 3.1//, 2.4, 1.7, 1.0, 0.6 
        };
        List<Double> todos = new ArrayList(Arrays.asList(vectorTodos));
        int n = todos.size();

        Collections.sort(todos);
        Collections.reverse(todos);
        todos.forEach((numero) -> {System.out.println(numero);}); System.out.println("####");
        cuadroIzquierdo = new ArrayList();
        cuadroDerecho = new ArrayList();
        for (double numero : todos) {
            if (totalCuadroIzquierdo > totalCuadroDerecho) {
                if (cuadroDerecho.size() < n/2) {
                    cuadroDerecho.add(numero);
                    totalCuadroDerecho += numero;
                } else {
                    cuadroIzquierdo.add(numero);
                    totalCuadroIzquierdo += numero;
                }
            } else {
                if (cuadroIzquierdo.size() < n/2) {
                    cuadroIzquierdo.add(numero);
                    totalCuadroIzquierdo += numero;
                } else {
                    cuadroDerecho.add(numero);
                    totalCuadroDerecho += numero;
                }
            }
            add();
        }

        cuadroIzquierdo.forEach((numero) -> {System.out.println(numero);}); System.out.println("----"); System.out.println(df.format(totalCuadroIzquierdo));
        System.out.println("****");
        cuadroDerecho.forEach((numero) -> {System.out.println(numero);}); System.out.println("----"); System.out.println(df.format(totalCuadroDerecho));
    }

    private static void add() {
        double totalCuadroMayor;
        double totalCuadroMenor;
        ArrayList<Double> cuadroMayor;
        ArrayList<Double> cuadroMenor;
        boolean cuadroIzquierdoMayor;

        if (totalCuadroIzquierdo > totalCuadroDerecho) {
            cuadroMayor = new ArrayList(cuadroIzquierdo);
            cuadroMenor = new ArrayList(cuadroDerecho);
            totalCuadroMayor = totalCuadroIzquierdo;
            totalCuadroMenor = totalCuadroDerecho;
            cuadroIzquierdoMayor = true;
        } else {
            cuadroMayor = new ArrayList(cuadroDerecho);
            cuadroMenor = new ArrayList(cuadroIzquierdo);
            totalCuadroMayor = totalCuadroDerecho;
            totalCuadroMenor = totalCuadroIzquierdo;
            cuadroIzquierdoMayor = false;
        }

        ArrayList mCuadroMayor = new ArrayList(cuadroMayor);
        ArrayList mCuadroMenor = new ArrayList(cuadroMenor);
        for (double maxCuadroMayor : cuadroMayor) {
            for (double maxCuadroMenor : cuadroMenor) {
                if (totalCuadroMayor - totalCuadroMenor > maxCuadroMayor - maxCuadroMenor && maxCuadroMayor > maxCuadroMenor) {
                    mCuadroMayor.remove(maxCuadroMayor);
                    mCuadroMayor.add(maxCuadroMenor);
                    mCuadroMenor.remove(maxCuadroMenor);
                    mCuadroMenor.add(maxCuadroMayor);
                    totalCuadroMayor = totalCuadroMayor - maxCuadroMayor + maxCuadroMenor;
                    totalCuadroMenor = totalCuadroMenor - maxCuadroMenor + maxCuadroMayor;
                    maxCuadroMayor = maxCuadroMenor;
                }
            }
            cuadroMenor.clear();
            cuadroMenor.addAll(mCuadroMenor);
        }
        cuadroMayor.clear();
        cuadroMayor.addAll(mCuadroMayor);

        cuadroIzquierdo.clear();
        cuadroDerecho.clear();
        if (cuadroIzquierdoMayor) {
            cuadroIzquierdo.addAll(cuadroMayor);
            cuadroDerecho.addAll(cuadroMenor);
            totalCuadroIzquierdo = totalCuadroMayor;
            totalCuadroDerecho = totalCuadroMenor;
        } else {
            cuadroDerecho.addAll(cuadroMayor);
            cuadroIzquierdo.addAll(cuadroMenor);
            totalCuadroDerecho = totalCuadroMayor;
            totalCuadroIzquierdo = totalCuadroMenor;
        }
        Collections.sort(cuadroIzquierdo);
        Collections.reverse(cuadroIzquierdo);
        Collections.sort(cuadroDerecho);
        Collections.reverse(cuadroDerecho);
    }
}