Точка, покрывающая проблему

У меня недавно была эта проблема на тесте: учитывая ряд точек 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!) время?

Спасибо

7
задан Sean 12 May 2010 в 19:31
поделиться

2 ответа

Ваш жадный алгоритм ЕСТЬ правильный. Мы можем доказать это, показав, что ЛЮБОЕ другое покрытие может быть улучшено только путем замены его на покрытие, полученное вашим алгоритмом.

Пусть C - допустимое покрытие для данного входа (не обязательно оптимальное), и пусть S - покрытие, полученное вашим алгоритмом. Теперь рассмотрим точки p1, p2, ... pk, которые представляют собой минимальные точки, с которыми вы имеете дело на каждом шаге итерации. Покрытие C должно покрывать их все. Обратите внимание, что в C нет отрезка, покрывающего две из этих точек; иначе ваш алгоритм выбрал бы этот отрезок! Следовательно, |C|>=k. А какова стоимость (количество сегментов) в вашем алгоритме? |S|=k.

На этом доказательство закончено.

Два замечания:

1) Реализация: Инициализация bestLine значением n[0] неверна, так как цикл может быть не в состоянии улучшить его, а n[0] не обязательно покрывает minX.

2) На самом деле эта задача является упрощенной версией задачи Set Cover. В то время как оригинал является NP-полным, эта вариация оказывается полиномиальной.

7
ответ дан 7 December 2019 в 07:41
поделиться

Подсказка: сначала попробуйте доказать, что ваш алгоритм работает для наборов размера 0, 1, 2 ... и посмотрите, сможете ли вы обобщить это, чтобы создать доказательство, индукция.

0
ответ дан 7 December 2019 в 07:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: