找到最小数量的列

时间:2016-05-24 12:11:58

标签: java algorithm data-structures acm

这是一个例子: 假设我有一个只包含0和1的二维数组:

0,1,0,0
0,0,0,1
1,0,1,0

我需要找到可以加到一个向量的最小数量的列。例如, column0 + column1 + column3 = 0,0,1 + 1,0,0 + 0,1,0 = 1,1,1 因此,最小列数为3。

2 个答案:

答案 0 :(得分:3)

这基本上是Set cover problem,这是NP难的。它可以作为整数线性规划问题进行公式化和求解(最佳)。

您还可以将问题转换为具有非常好的解算器的同一类的另一个问题,例如:布尔SAT。

最后,但并非最不重要的是,您可以使用贪婪和/或本地搜索算法来解决它,例如:模拟退火。

答案 1 :(得分:0)

无耻地复制来自https://stackoverflow.com/a/34588366/1203882

的组合代码
import java.util.ArrayList;
import java.util.List;

public class Combin {

    public static void main(String... banana) {
        int[][] input = new int[][] { { 0, 1, 0, 0 }, { 0, 0, 0, 1 }, { 1, 0, 1, 0 } };
        List<int[]> columns = new ArrayList<int[]>();
        int min = Integer.MAX_VALUE;

        //Set columns list
        for (int column = 0; column < input[0].length; column++) {
            int[] e = new int[input.length];
            int index = 0;
            for (int row = 0; row < input.length; row++) {
                e[index++] = input[row][column];
            }
            columns.add(e);
        }

        //Sizes 0 1 2 3 and 4
        for (int i = 0; i <= columns.size(); i++)
        {
            List<List<int []>> theList = getCombinations(i, columns);
            for (List <int[]> a : theList)
            {
                if (check(a))
                {
                    if (a.size() < min)
                        min = a.size();

                    //For the test returns 3, 3, and 4 as possibilities.
                    System.out.println("Found a possibility: " + a.size());
                }
            }
        }
        System.out.println("Min value: " + min);
    }

    public static <T> List<List<T>> getCombinations(int k, List<T> list) {
        List<List<T>> combinations = new ArrayList<List<T>>();
        if (k == 0) {
            combinations.add(new ArrayList<T>());
            return combinations;
        }
        for (int i = 0; i < list.size(); i++) {
            T element = list.get(i);
            List<T> rest = getSublist(list, i+1);
            for (List<T> previous : getCombinations(k-1, rest)) {
                previous.add(element);
                combinations.add(previous);
            }
        }
        return combinations;
    }

    public static <T> List<T> getSublist(List<T> list, int i) {
        List<T> sublist = new ArrayList<T>();
        for (int j = i; j < list.size(); j++) {
            sublist.add(list.get(j));
        }
        return sublist;
    }  

    //Create a vector by "or"ing every value.
    public static boolean check(List<int []> result)
    {   
        if (result.size() == 0)
            return false;
        int [] a = new int [result.get(0).length];
        for(int [] j : result)
            for (int index = 0; index < a.length; index++)
                a[index] |= j[index];
        return equalsVec(a);
    }

    //If all values aren't 1, return false. (ones vector)
    public static boolean equalsVec(int [] a)
    {
        for (int i = 0; i < a.length; i++)
            if (a[i] != 1)
                return false;
        return true;
    }
}

输出:

Found a possibility: 3
Found a possibility: 3
Found a possibility: 4
Min value: 3