У меня есть комбинаторная задача, которую можно неэффективно решить, используя декартово произведение нескольких множеств. Конкретно, у меня есть несколько элементов и несколько элементов, которые удовлетворяют каждому элементу. Задача состоит в том, чтобы найти все возможные комбинации элементов, удовлетворяющие всем пунктам. Например:
items -> elements
------------------------
1 -> {a,b} // a and b cover the item 1
2 -> {a,b} // a and b cover the item 2
3 -> {a,b,c} // a, b and c cover the item 3
4 -> {a,b,e,f} // a, b, e, f cover the item 4
Alternative representation:
element -> items covered
------------------------
a -> {1,2,3,4}
b -> {1,2,3,4}
c -> {3}
e -> {4}
f -> {4}
Цель состоит в том, чтобы найти все комбинации, которые охватывают пункты 1,2,3,4. Допустимые решения:
{a},{a,b},{a,c},{a,e},{a,f},{a,b,c},{a,b,e},{a,b,f},{a,b,c,e},{a,b,c,f}
{b},{b,c},{b,e},{b,f},{b,c,e},{b,c,f}
Обратите внимание, что порядок не важен, поэтому {a,b} = {b,a} ({a,b} x {c,d} = {c,d} x {a,b})
. Также обратите внимание, что {a,a,a,a}, {a,a,a,b}...
являются избыточными комбинациями.
Как видите, эта задача аналогична задаче set cover problem
, где вселенная элементов для этого примера — это элементы U={1,2,3,4}
, а набор подмножеств из U — S={ab={1,2,3,4},c={3},ef{4}}
, где набор {1,2,3,4}
— это набор элементов, покрываемых элементами a
и b
. , {3}
— это набор элементов, покрываемых c
, а {4}
— это набор элементов, покрываемых элементами e
и f
. Однако цель здесь не в том, чтобы найти минимальную комбинацию наборов из S
, которая покрывает все элементы из U
, а в том, чтобы найти все комбинации элементов {a,b,c,e,f}
, которые охватывают все элементы {1,2,3,4}
.
Простую реализацию можно было бы реализовать, выполнив декартово произведение между наборами для 1, 2, 3 и 4, а затем отфильтровав избыточные комбинации. Однако такой подход очень неэффективен. Предположим, у меня есть такая ситуация:
1 -> {a,b,c,d,e,f,g,h}
2 -> {a,b,c,d,e,f,g,h}
3 -> {a,b,c,d,e,f,g,h}
4 -> {a,b,c,d,e,f,g,h}
5 -> {a,b,c,d,e,f,g,h}
6 -> {a,b,c,d,e,f,g,h,i}
Декартово произведение шести наборов даст 8^5*9=294912
комбинаций, тогда как на самом деле комбинаций намного меньше, а именно: {a,b,c,d,e,f,g} U {a,b,c,d,e,f,g} x {i}
.
Другой способ решить эту проблему — перебрать все элементы, пропустив комбинации, эквивалентные другим ранее сгенерированным, а также пропустив повторяющиеся элементы. Это довольно легко вычислить, и его можно реализовать как итератор, который возвращает комбинацию за раз, но я не знаю, есть ли лучший способ решить эту проблему, или эта проблема изучалась ранее.
Как бы вы решили эту проблему?
{a,b,e}
в качестве допустимого решения в своем первом примере? Это потому, что вы указали только некоторые из допустимых комбинаций? Кстати, я добавил к своему ответу код Haskell, который дает немедленный результат для двух приведенных примеров ... насколько большими, по вашему мнению, будут входные данные? - person גלעד ברקן   schedule 25.04.2013