У меня недавно была эта проблема на тесте: учитывая ряд точек m (все на оси X) и набор n строк с конечными точками [l, r] (снова на оси X), находят минимальное подмножество n таким образом, что на все вопросы отвечает строка. Докажите, что Ваше решение всегда находит минимальное подмножество.
Алгоритм, который я записал для него, был чем-то к эффекту: (скажите, что строки хранятся как массивы с левой конечной точкой в положении 0 и правом в положении 1),
algorithm coverPoints(set[] m, set[][] n):
chosenLines = []
while m is not empty:
minX = min(m)
bestLine = n[0]
for i=1 to length of n:
if n[i][0] <= minX and n[i][1] > bestLine[1] then
bestLine = n[i]
add bestLine to chosenLines
for i=0 to length of m:
if m[i] <= bestLine[1] then delete m[i] from m
return chosenLines
Я просто не уверен, находит ли это всегда минимальное решение. Это - простой жадный алгоритм, таким образом, мой пищеварительный тракт говорит мне, что это не будет, но один из моих друзей, который намного лучше, чем я в этом, говорит, что для этой проблемы жадный алгоритм как это всегда находит минимальное решение. Для доказательства мой всегда находит минимальное решение, я сделал очень ручное волнистое доказательство противоречием, где я сделал предположение, которое, вероятно, не верно вообще. Я забываю точно, что я сделал.
Если это не минимальное решение, есть ли способ сделать это в меньше, чем что-то как O (n!) время?
Спасибо
Ваш жадный алгоритм ЕСТЬ правильный. Мы можем доказать это, показав, что ЛЮБОЕ другое покрытие может быть улучшено только путем замены его на покрытие, полученное вашим алгоритмом.
Пусть C - допустимое покрытие для данного входа (не обязательно оптимальное), и пусть S - покрытие, полученное вашим алгоритмом. Теперь рассмотрим точки p1, p2, ... pk, которые представляют собой минимальные точки, с которыми вы имеете дело на каждом шаге итерации. Покрытие C должно покрывать их все. Обратите внимание, что в C нет отрезка, покрывающего две из этих точек; иначе ваш алгоритм выбрал бы этот отрезок! Следовательно, |C|>=k. А какова стоимость (количество сегментов) в вашем алгоритме? |S|=k.
На этом доказательство закончено.
Два замечания:
1) Реализация: Инициализация bestLine значением n[0] неверна, так как цикл может быть не в состоянии улучшить его, а n[0] не обязательно покрывает minX.
2) На самом деле эта задача является упрощенной версией задачи Set Cover. В то время как оригинал является NP-полным, эта вариация оказывается полиномиальной.
Подсказка: сначала попробуйте доказать, что ваш алгоритм работает для наборов размера 0, 1, 2 ... и посмотрите, сможете ли вы обобщить это, чтобы создать доказательство, индукция.