Обложка минимального набора - это вопрос, в котором вы должны найти минимальное количество наборов, необходимое для покрытия каждого элемента.
Например, представьте, что у нас есть набор X=array(1,2,3,4,5,6)
и еще 5 наборов S, где
S[1]=array(1, 4)
S[2] =array(2, 5)
S[3] =array(3, 6)
S[4] =array(1, 2, 3)
S[5] =array(4, 5, 6)
Проблема состоит в том, чтобы найти минимальное количество наборов S
, которые охватывают каждый элемент X.
Так что очевидно, что минимальное покрытие наборов в нашем случае будет S [4] и S [5], потому что они охватывают все элементы .
У кого-нибудь есть идеи, как реализовать этот код в PHP. Обратите внимание, что это NP-complete , поэтому нет быстрого алгоритма для его решения. Любое решение в PHP будет приветствоваться. И кстати, это не домашняя работа, мне нужно использовать этот алгоритм в моем веб-приложении, чтобы создать список предложений.
Заранее спасибо.
Обновление 1
Есть много приложений Задачи Покрытия Сета. Вот некоторые из интересных:
- Построение оптимальных логических схем
- Расписание воздушного экипажа
- Сборочный конвейер балансировки
- Поиск информации
- Художественная галерея задача
- секвенирование генома
- Красно-синяя проблема SetCover
Обновление 2
Например, здесь вы можете увидеть рабочую версию упомянутой проблемы. Здесь даже видно визуально наборы. Но мне нужен чистый PHP-код для этого, если у кого-то есть, пожалуйста, предоставьте нам рабочий пример на PHP. Спасибо
Обновление 3
Наконец, я решил проблему в PHP. Мое решение основано на алгоритме, предложенном в очень известной книге под названием Введение в алгоритмы , раздел Задача о покрытии множеств . Вот как выглядит мое решение:
$MainSet=array(1, 2, 3, 4, 5, 6, 7);
$SubSet=array(array(1,4), array(2, 5), array(3, 6), array(1, 2, 3), array(4, 5, 6));
$UncoveredElements=$MainSet;
$CoveringSets=array();
while (count($UncoveredElements)>0){
$S=SubSetS($UncoveredElements, $SubSet);
if (is_array($S)){
$UncoveredElements=array_diff($UncoveredElements, $S);
$CoveringSets[]=$S;
}else
break; //finish work
}
echo "Sets that cover MainSet are:";
var_dump($CoveringSets);
//Subset S is chosen that covers as many uncovered elements as possible
function SubSetS($UncoveredElements, $SubSetArr){
$max=0; $s=array();
foreach($SubSetArr as $SubSet){
$intersectArr=array_intersect($UncoveredElements, $SubSet);
$weight=count($intersectArr);
if ($weight>$max){
$max=$weight;
$s=$SubSet;
}
}
if ($max>0)
return $s;
else
return 0;
}
Есть комментарии и идеи по поводу моего решения? Для меня это решает мою проблему, это то, что я хотел. Но если вы предлагаете какую-либо оптимизацию, исправление кода, пожалуйста, заполните бесплатно.
Кстати, большое спасибо участникам вопроса за их ценные ответы.
Окончательное обновление
Этот жадный подход к задаче покрытия множеств не всегда гарантирует оптимальное решение. Рассмотрим следующий пример:
Дано: элементы основного набора = {1, 2, 3, 4, 5, 6}
Теперь рассмотрим 4 подмножества следующим образом: Подмножество 1 = {1, 2}, Подмножество 2 = {3, 4}, Подмножество 3 = {5, 6}, Подмножество 4 = {1, 3, 5}.
Алгоритм Жадности для вышеупомянутого набора Подмножеств дает Минимальное Покрытие Набора как:
Обложка минимального набора содержит подмножества = {1, 2, 3, 4}.
Таким образом, хотя минимальный набор подмножеств, охватывающий все элементы основного набора, - это первые три подмножества , мы получаем решение, содержащее все 4 подмножества.