Дан псевдокод жадного алгоритма для задачи покрытия множества; приведите контрпример, показывающий, что жадный подход даёт ненаправильное (недостаточно хорошее) решение, проанализируйте аппроксимационную границу алгоритма и предложите улучшения или альтернативы (например, локальный поиск, линейное программирование с округлением)
Контрпример (простой, показывает, что жадный не всегда оптимален). Пусть U={a,b,c}U=\{a,b,c\}U={a,b,c} и коллекция множеств с весами: - S1={a,b}, w(S1)=3S_1=\{a,b\},\; w(S_1)=3S1={a,b},w(S1)=3
- S2={b,c}, w(S2)=3S_2=\{b,c\},\; w(S_2)=3S2={b,c},w(S2)=3
- S3={a,b,c}, w(S3)=5S_3=\{a,b,c\},\; w(S_3)=5S3={a,b,c},w(S3)=5 Жадный алгоритм по правилу «минимальный стоимость/новые\ элементы» сначала сравнивает: w(S1)∣S1∣=3/2=1.5, w(S2)∣S2∣=1.5, w(S3)∣S3∣=5/3≈1.667\frac{w(S_1)}{|S_1|}=3/2=1.5,\; \frac{w(S_2)}{|S_2|}=1.5,\; \frac{w(S_3)}{|S_3|}=5/3\approx1.667∣S1∣w(S1)=3/2=1.5,∣S2∣w(S2)=1.5,∣S3∣w(S3)=5/3≈1.667. Он выберет, скажем, S1S_1S1, затем потребуется покрыть ccc — выбор S2S_2S2 даёт итоговую стоимость 3+3=63+3=63+3=6. Но оптимум — взять S3S_3S3 с весом 555. Итого жадный дал решение хуже оптимального (отношение 6/56/56/5). Анализ аппроксимационной границы. Для задачи покрытия множества жадный алгоритм даёт приближение Hn=1+12+13+⋯+1n≈lnn\displaystyle H_{n}=1+\tfrac12+\tfrac13+\dots+\tfrac1n\approx\ln nHn=1+21+31+⋯+n1≈lnn, где n=∣U∣n=|U|n=∣U∣. Короткая доказательная идея (неформально): - Пусть оптимум требует kkk множеств (или имеет стоимость OPTOPTOPT в весовом варианте). В любой текущей непокрытой части остаётся не более rrr элементов; среди множеств оптимума есть одно, покрывающее как минимум r/kr/kr/k оставшихся элементов. Значит жадный шаг покрывает ≥ r/k\,r/kr/k элементов, и последовательное суммирование даёт, что число выбранных множеств ≤ k⋅Hnk\cdot H_nk⋅Hn. В весовом варианте аналогично через зарядное рассуждение или двойственную оценку получается Costgreedy≤OPT⋅HnCost_{greedy}\le OPT\cdot H_nCostgreedy≤OPT⋅Hn. Этот предел асимптотически точен: существуют семейства, где отношение жадного к оптимальному достигает Θ(lnn)\Theta(\ln n)Θ(lnn). Также известно, что улучшить фактор lnn\ln nlnn полиномиальным алгоритмом в общем случае нельзя (кроме очень малых фактов), т.е. логарифмическая граница почти тайтна. Улучшения и альтернативы - Предобработка: удалить доминируемые множества и элементы с одинаковыми покрытиями; это часто улучшает практику. - Локальный поиск (k-exchange): начать с решения (например, жадного) и пытаться улучшать заменой ≤kkk множеств на ≤k−1k-1k−1 — даёт практический выигрыш, при больших kkk может найти близкие к оптимуму решения. - LP-релаксация и округление: решить LP min∑Sw(S)xS\displaystyle \min\sum_S w(S)x_SminS∑w(S)xS при ограничениях ∑S∋exS≥1\sum_{S\ni e} x_S\ge1∑S∋exS≥1 для всех eee, xS≥0x_S\ge0xS≥0. Затем применять округление (например, пороговое или рандомизированное) — стандартный подход даёт аппроксимацию O(lnn)O(\ln n)O(lnn) и часто практический результат лучше, плюс LP даёт нижнюю оценку для отбора. - Примально-двойственные алгоритмы и жадные варианты с доработкой: похожи на классический greedy, но аккуратно масштабируют веса — улучшают стабильность и дают те же гаранты. - Специальные методы для частных случаев: для геометрических покрытий, покрытий с ограниченной частотой элементов (element frequency fff) можно получить приближения fff или O(logf)O(\log f)O(logf), а иногда PTAS. - Целочисленное программирование + MIP-решатель: для средних размеров инстансов часто даёт оптимум или очень хорошие решения. Резюме: жадный прост и даёт гарантию Hn≈lnnH_n\approx\ln nHn≈lnn, но может быть логарифмически хуже оптимума; в практике эффективны LP-округления, локальный поиск, примально-двойственные схемы и специальные эвристики в зависимости от структуры задачи.
- S1={a,b}, w(S1)=3S_1=\{a,b\},\; w(S_1)=3S1 ={a,b},w(S1 )=3 - S2={b,c}, w(S2)=3S_2=\{b,c\},\; w(S_2)=3S2 ={b,c},w(S2 )=3 - S3={a,b,c}, w(S3)=5S_3=\{a,b,c\},\; w(S_3)=5S3 ={a,b,c},w(S3 )=5
Жадный алгоритм по правилу «минимальный стоимость/новые\ элементы» сначала сравнивает:
w(S1)∣S1∣=3/2=1.5, w(S2)∣S2∣=1.5, w(S3)∣S3∣=5/3≈1.667\frac{w(S_1)}{|S_1|}=3/2=1.5,\; \frac{w(S_2)}{|S_2|}=1.5,\; \frac{w(S_3)}{|S_3|}=5/3\approx1.667∣S1 ∣w(S1 ) =3/2=1.5,∣S2 ∣w(S2 ) =1.5,∣S3 ∣w(S3 ) =5/3≈1.667.
Он выберет, скажем, S1S_1S1 , затем потребуется покрыть ccc — выбор S2S_2S2 даёт итоговую стоимость 3+3=63+3=63+3=6. Но оптимум — взять S3S_3S3 с весом 555. Итого жадный дал решение хуже оптимального (отношение 6/56/56/5).
Анализ аппроксимационной границы. Для задачи покрытия множества жадный алгоритм даёт приближение
Hn=1+12+13+⋯+1n≈lnn\displaystyle H_{n}=1+\tfrac12+\tfrac13+\dots+\tfrac1n\approx\ln nHn =1+21 +31 +⋯+n1 ≈lnn,
где n=∣U∣n=|U|n=∣U∣. Короткая доказательная идея (неформально):
- Пусть оптимум требует kkk множеств (или имеет стоимость OPTOPTOPT в весовом варианте). В любой текущей непокрытой части остаётся не более rrr элементов; среди множеств оптимума есть одно, покрывающее как минимум r/kr/kr/k оставшихся элементов. Значит жадный шаг покрывает ≥ r/k\,r/kr/k элементов, и последовательное суммирование даёт, что число выбранных множеств ≤ k⋅Hnk\cdot H_nk⋅Hn . В весовом варианте аналогично через зарядное рассуждение или двойственную оценку получается Costgreedy≤OPT⋅HnCost_{greedy}\le OPT\cdot H_nCostgreedy ≤OPT⋅Hn .
Этот предел асимптотически точен: существуют семейства, где отношение жадного к оптимальному достигает Θ(lnn)\Theta(\ln n)Θ(lnn). Также известно, что улучшить фактор lnn\ln nlnn полиномиальным алгоритмом в общем случае нельзя (кроме очень малых фактов), т.е. логарифмическая граница почти тайтна.
Улучшения и альтернативы
- Предобработка: удалить доминируемые множества и элементы с одинаковыми покрытиями; это часто улучшает практику.
- Локальный поиск (k-exchange): начать с решения (например, жадного) и пытаться улучшать заменой ≤kkk множеств на ≤k−1k-1k−1 — даёт практический выигрыш, при больших kkk может найти близкие к оптимуму решения.
- LP-релаксация и округление: решить LP
min∑Sw(S)xS\displaystyle \min\sum_S w(S)x_SminS∑ w(S)xS при ограничениях ∑S∋exS≥1\sum_{S\ni e} x_S\ge1∑S∋e xS ≥1 для всех eee, xS≥0x_S\ge0xS ≥0.
Затем применять округление (например, пороговое или рандомизированное) — стандартный подход даёт аппроксимацию O(lnn)O(\ln n)O(lnn) и часто практический результат лучше, плюс LP даёт нижнюю оценку для отбора.
- Примально-двойственные алгоритмы и жадные варианты с доработкой: похожи на классический greedy, но аккуратно масштабируют веса — улучшают стабильность и дают те же гаранты.
- Специальные методы для частных случаев: для геометрических покрытий, покрытий с ограниченной частотой элементов (element frequency fff) можно получить приближения fff или O(logf)O(\log f)O(logf), а иногда PTAS.
- Целочисленное программирование + MIP-решатель: для средних размеров инстансов часто даёт оптимум или очень хорошие решения.
Резюме: жадный прост и даёт гарантию Hn≈lnnH_n\approx\ln nHn ≈lnn, но может быть логарифмически хуже оптимума; в практике эффективны LP-округления, локальный поиск, примально-двойственные схемы и специальные эвристики в зависимости от структуры задачи.