找到所有套装的组合 - 套装?

时间:2010-11-26 17:12:36

标签: java algorithm

有人可以在java中共享程序,执行以下操作。 如果给出以下几组作为输入,

a={1,2,3,8,9,10}
b={1,2,3,4,5}
c={4,5,7}
d={5,6,7}
e={6,7,8,9,10}

U={1,2,3,4,5,6,7,8,9,10}

程序将找到该组的所有组合,并找出共同具有U的所有元素的最小组数。

在上面的例子中,最小数字是2. set b和e一起覆盖了U的全部。 所以基本上,它是一个集合覆盖问题。在Set Covering问题中,我们给出了一个Universe U,例如|U|=n和集S1,……,Sk是U的子集。集合封面是来自{{1}的一些集合的集合C.其联盟是整个宇宙U.此外,我们必须最小化集合的成本。

4 个答案:

答案 0 :(得分:4)

您需要的是测试不断增加的组合大小,例如

interface Filter<T> {
    boolean matches(T t);
}
public static void main(String... args) throws IOException {
    Integer[][] arrayOfSets = {
            {1, 2, 3, 8, 9, 10},
            {1, 2, 3, 4, 5},
            {4, 5, 7},
            {5, 6, 7},
            {6, 7, 8, 9, 10},
    };
    Integer[] solution = {1,2,3,4,5,6,7,8,9,10};

    List<Set<Integer>> listOfSets = new ArrayList<Set<Integer>>();
    for (Integer[] array : arrayOfSets)
        listOfSets.add(new LinkedHashSet<Integer>(Arrays.asList(array)));
    final Set<Integer> solutionSet = new LinkedHashSet<Integer>(Arrays.asList(solution));

    Filter<Set<Set<Integer>>> filter = new Filter<Set<Set<Integer>>>() {
        public boolean matches(Set<Set<Integer>> integers) {
            Set<Integer> union = new LinkedHashSet<Integer>();
            for (Set<Integer> ints : integers)
                union.addAll(ints);
            return union.equals(solutionSet);
        }
    };

    Set<Set<Integer>> firstSolution = shortestCombination(filter, listOfSets);
    System.out.println("The shortest combination was "+firstSolution);
}

private static <T> Set<T> shortestCombination(Filter<Set<T>> filter, List<T> listOfSets) {
    final int size = listOfSets.size();
    if (size > 20) throw new IllegalArgumentException("Too many combinations");
    int combinations = 1 << size;
    List<Set<T>> possibleSolutions = new ArrayList<Set<T>>();
    for(int l = 0;l<combinations;l++) {
        Set<T> combination = new LinkedHashSet<T>();
        for(int j=0;j<size;j++) {
            if (((l >> j) & 1) != 0)
                combination.add(listOfSets.get(j));
        }
        possibleSolutions.add(combination);
    }
    // the possible solutions in order of size.
    Collections.sort(possibleSolutions, new Comparator<Set<T>>() {
        public int compare(Set<T> o1, Set<T> o2) {
            return o1.size()-o2.size();
        }
    });
    for (Set<T> possibleSolution : possibleSolutions) {
        if (filter.matches(possibleSolution))
            return possibleSolution;
    }
    return null;
}

打印

The shortest combination was [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]

答案 1 :(得分:1)

由于您需要最佳解决方案,并且由于set cover是NP完全的,因此只需通过强力生成所有可能的组合。对于n集的输入,将有2^n - 1种可能的组合。您可以依次生成每个组合:

let the input sets be S1, S2, ..., Sn
let min = { S1, S2, ..., Sn } // initially assume all sets are required
for i = 1, 2, ..., 2^n - 2
  let X = {}
  represent i as a binary number containing n bits
  for each bit j that is set to 1, include set Sj in X
  if X covers all sets and #X < #min
    update min = X
end

答案 2 :(得分:1)

对于迟到的回复感到抱歉。但是如果您仍然对此感兴趣,可以使用Rajagopalan-Vazirani算法获得近似解决方案来设置封面:http://portal.acm.org/citation.cfm?id=299880。这将为您提供最多距离最佳因素2的答案。

答案 3 :(得分:0)

I代表到目前为止包含的元素集。

  1. 初始化I = {}

  2. IU不同的情况下执行关注

    • a)在Si中找到成本效益最小的集合{S1, S2, ... Sm}
    • b)将上面选择的Si的元素添加到I,即I = I U Si