Скачиваний:
48
Добавлен:
30.05.2020
Размер:
689.54 Кб
Скачать

z

Запитання для самоконтролю

1. Що собою являє динамічне програмування?

 

2. Які відмінності між задачами лінійного і динамічного програму­

 

вання?

 

3. Чому задачі динамічного програмування називають багатоетап-

 

ними?

 

4. Як формулюється ідея розв'язування задач динамічного програ­

 

мування?

 

5. Як схематично можна представити ідею розв'язування задач ди­

 

намічного програмування?

 

6. Чому задачі динамічного програмування можна віднести до оп-

 

тимізаційних задач?

 

7. Продемонструйте на власному прикладі поетапне розв'язуван­

 

ня задачі про. прокладання найвигіднішого шляху між двома

 

пунктами методом динамічного програмування. Обґрунтуйте

 

можливість розв'язання цієї задачі саме методом динамічного

 

програмування.

 

8. Продемонструйте на власному прикладі поетапне розв'язуван­

 

ня задачі про найбільшу спільну підпослідовність методом ди­

 

намічного програмування. Обґрунтуйте можливість розв'язання

 

цієї задачі саме методом динамічного програмування.

 

9. Продемонструйте на власному прикладі поетапне розв'язу­

 

вання задачі про розподіл ресурсів методом динамічного про­

 

грамування. Обґрунтуйте можливість розв'язання цієї задачі

 

саме методом динамічного програмування.

10.Продемонструйте на власному прикладі поетапне розв'язання задачі про рюкзак методом динамічного програмування. Обґрунтуйте можливість розв'язання цієї задачі саме методом динамічного програмування.

11.Як формулюється загальна задача динамічного програмування в алгоритмічних термінах?

12.Як формулюється принцип оптимальності Беллмана? Розтлу­ мачте принцип оптимальності на розв'язаних раніше конкретних прикладах.

13.Як знайти оптимальну стратегію розв'язаної задачі динамічного програмування?

14.Чи можна задачі динамічного програмування розв'язувати з «початку» в «кінець»? Обґрунтуйте свою відповідь.

15.Як розпізнати задачу динамічного програмування? Наведіть ос­ новні критерії визначення задачі динамічного програмування.

16.Які основні загальні підходи до розв'язування задач динамічно­ го програмування?

0 1 0 1 0 1 0 1 0 1

0 110

110

Н

 

 

1

111 в 0 1

1

 

 

0 0 110 110 10

 

ЖАДІБНІ АЛГОРИТМИ

10 1 1 1 0 0

0 1

 

 

1 0 01

0 111

 

 

0 0 0

0 110 1

 

 

 

10 10 0

10 1

 

 

іі р і 1 0 1 0 0 1

і

^яш(¥

о

: он ґб'ї.і "

 

і о і і

о

о

і

 

 

О

0 0

 

і

 

 

 

1

0

 

1

 

 

 

Уже не один раз ми говорили про жадібний підхід до побудо­ ви алгоритму.

На відміну від задач динамічного програмування, жадібні алгоритми оптимально розв'язують кожний етап задачі як окрему, незалежну задачу. Від розв'язку кожного окремого етапу не залежать оптимальні розв'язки всіх інших етапів. Такий алгоритм щоразу (на кожному кроці) робить локально оптимальний вибір у надії, що результуючий розв'язок ви­ явиться також оптимальним. Це не завжди так, але для бага­ тьох задач жадібні алгоритми є справді оптимальними.

Прикладами задач, що розв'язувалися жадібними алго­ ритмами, є алгоритм Краскала про визначення мінімального остовного дерева заданого графа та алгоритм Дейкстри визна­ чення найкоротшого шляху між заданими вершинами у графі. У першому алгоритмі на кожній ітерації його виконання ви­ значалося наступне ребро, як найменше серед ще не розгляну­ тих і таке, що не утворює цикл із вже розглянутими ребрами. За алгоритмом Дейкстри на кожному поточному кроці серед невідвіданих вершин вибирається вершина, що розміщена найближче до верпіини-джерела.

Удеяких ситуаціях жадібні алгоритми можна вважати ев­ ристичними. Наприклад, якщо невідомі оптимальні розв'язки заданої задачі і єдиним способом отримання найкращого розв'язку є повний перебір усіх варіантів, то можливо саме жадібний алгоритм може виявитися єдиним реальним засобом досягнення результату.

Усвою чергу серед евристичних алгоритмів інколи трапляються жадібні. Вони характерні тим, що не для всіх ви­ падків дають оптимальні розв'язки. Однак якщо не відомо іншого кращого алгоритму, то можна вважати задовільним і «майже оптимальний» розв'язок.

Перш ніж перейти до обґрунтування доцільності викорис­ тання жадібних алгоритмів, розглянемо кілька прикладів.

233

Задача про центи

Нехай є монети номіналом 25, 10, 5 та 1 цент. Якою наймен­ шою кількістю монет можна видати суму S центів? На думку зразу ж інтуїтивно спадає такий алгоритм розв'язування цієї задачі: спочатку візьмемо максимально можливу кількість монет номіналом 25 центів, але так, щоб ця сума не перевищу­ вала S. Потім визначимо, скільки монет номіналом 10 центів не перевищить залишку від S. Ту саму операцію проведемо із монетою номіналом 5 центів. Остаточний залишок видамо мо­ нетами 1 цент.

Цей алгоритм без сумніву можна назвати жадібним і записа­ ти у такому вигляді:

1.Спочатку визначити максимальне п, для якого 25 * n <= S.

2.Якщо S - 25 * п > 0, то визначити максимальне пг, для якого 10 * m<= S - 25 * п; у протилежному випадку перейти до п. 5.

3.Якщо S - 2 5 * 7 i - 1 0 * m > 0 , то визначити максимальне k, для якого 5 * f e < = S - 2 5 * n - 1 0 * m ; y протилежному випад­ ку перейти до п. 5.

4.Якщо S - 25 * п - 10 * т - 5 * Ш > 0, то суму S - 25 * п - 10 *

*т - 5 * k видати монетами номіналом 1 цент.

5.Завершити алгоритм.

Ураховуючи простоту і прозорість цього алгоритму, можна записати його мовою програмування без коментарів у такому вигляді:

sort;

і:=1;

while s > 0 do begin

m :=sdivc[i]; dec(s, m * c[i]);

writeln(f_out, c[i], ': ', m); inc(i);

end;

Чи завжди цей алгоритм дасть правильну відповідь? Можна запропонувати такий контрприклад: нехай загальна сума S становить 15 центів, а у нас є монети номіналом 1, 5, 11 центів. Виконавши описаний вище жадібний алгоритм для даної умо­ ви, отримаємо такий набір монет: 11, 1, 1, 1, 1. Але насправді оптимальною буде відповідь: 5, 5, 5. Чому так сталося? Невже наш алгоритм не є оптимальним? Справа в тім, що, визначаю­ чи доцільність використання жадібного алгоритму, необхідно оцінити ступінь ефективності його використання. Про це йти­ меться трохи пізніше, після розгляду кількох прикладів жадіб­ них алгоритмів. Однак для задачі про центи можна проаналізу­ вати доцільність використання жадібного алгоритму за умови

234

задання різних вхідних даних. Можливо, це залежить від вар­ тості монет? Спробуйте дати відповідь на це запитання.

Оцінку ефективності цього алгоритму визначити зовсім не складно, вона залежить лише від кількості монет, тобто стано­ вить 0(п).

Неперервна задача про рюкзак

Неперервна задача про рюкзак відрізняється від подібної за­ дачі, що формулювалася і розв'язувалася в попередньому розділі «Динамічне програмування», тим, що в рюкзак можна класти предмети, за необхідності попередньо роздроблюючи їх на частини. Можна вважати, наприклад, що в рюкзак склада­ ються різноманітні сипучі продукти. Нам відома загальна вага продуктів S, які можна скласти в рюкзак, кількість продуктів

пта їх запас, вартість одиниці об'єму кожного продукту. Знову ж таки алгоритм розв'язування цієї задачі напрочуд

простий, і його можна записати так.

1.Спочатку упорядкувати всі продукти за спаданням їх вар­

тості.

2.Визначити і = 1.

3.Взяти по максимуму і-й продукт і порахувати його вартість.

4.Якщо запас продукту і вичерпано, а рюкзак не заповнений, то перейти до п. 5; у протилежному випадку перейти до п. 6.

5.Якщо не всі продукти покладені у рюкзак (і К п), то роз­ глянути наступний продукт (і ':= і + 1) і перейти до п. 3.

6.Завершити алгоритм.

Представимо цей нескладний алгоритм без супроводжуючих коментарів мовою програмування:

sort;

і := 1; val := 0;

while (w[i] <= s) and (і <= n) do begin

dec(s, w[i]); writeln(f_out, i, ': ', w[i]); inc(val, w[i] * v[i]); inc(i);

end;

if s > 0 then

begin writeln(f_out, i,': ', s); inc(val, s * v[i]);

end; writeln(f_out, val);

Проаналізуємо, чи завжди сформульований алгоритм для за­ дачі про рюкзак у новій інтерпретації дасть оптимальний роз-

235

в'язок. Так, відповідь позитивна, оскільки, взявши перший про­ дукт максимально можливого об'єму, ми фактично при цьому зменшуємо заданий об'єм рюкзака, відкидаємо перший продукт і починаємо розв'язувати задачу спочатку для нових вхідних да­ них. Таким чином, наші етапи, якими є розгляд окремих про­ дуктів, незалежні і підсумковий оптимальний розв'язок, скла­ даються з оптимальних розв'язків кожного окремого етапу.

Оцінка ефективності цього алгоритму становить 0{п logn), оскільки основний час виконання піде на сортування послідов­ ності вартостей заданих продуктів.

Задача про заявки

Нехай задано п заявок на проведення занять в одній ауди­ торії. Для кожної заявки вказано початок st та кінець ft занят­ тя. Обов'язковою умовою є те, що два різних заняття не можуть перетинатися за часом. Якщо вони все ж таки перетинаються, то з них можна задовольнити лише одне. Будемо вважати, що збіг кінця однієї заявки з початком другої не є перетином. У за­ гальному випадку вважатимемо заявки [s;, ft) та [s., /,) такими, що не перетинаються, якщо для них виконується умова ft ^ s, або /. < sr Заявки, що не перетинаються, називатимемо сумісними. Задача полягає в тому, щоб визначити найбільшу кількість сумісних заявок.

Як і в попередній задачі, логічно було б якимось чином упо­ рядкувати інформацію про задані заявки. Нам відомі як час по­ чатку занять, так і час їх завершення. За яким параметром упо­ рядковувати інформацію: за першим чи за другим? Пропонуєть­ ся такий хід міркувань. Розглянемо дві заявки [sk, fk] і [s,,/,], для яких відомо, що заняття по першій починається раніше, ніж по другій sk < sr Є спокуса вибрати першу заявку, оскільки це за­ няття починається раніше. Однак не виключено, що закінчува­ тися воно буде пізніше за друге fk > fl і тоді ми можемо втратити одну або кілька заявок, для яких fk > ft (мал. 133). А от якщо ми порівнюватимемо інформацію про завершення часу занять відповідних заявок /;, які упорядковані за зростанням, то для прикладу, наведеного на малюнку 133, отримаємо більшу кількість сумісних заявок (мал. 134). Отже, можна для початку зробити такий висновок: першою заявкою, що входить до множини сумісних заявок максимальної кількості, є заявка з мінімальним значенням часу завершення заняття.

Відома також ще одна властивість двох сумісних заявок: /; < S-. А з цього факту можна зробити висновок, що для визначеної на поточному кроці заявки, що має час завершення заняття ft, треба знайти заявку, найближчу за часом початку заняття Sj, але одночасно таку, для якої час завершення / є найменшим

236

в,

sk

s ,

I HI

f,

fl

Мал. 133 Мал. 134

серед всіх заявок з часом, що не перевищує fr Простіше кажу­ чи, на кожному кроці для визначеної поточної заявки [st, ft] треба переглядати решту заявок [s , fj] у порядку зростання ча­ су їх завершення (ft ^ /) , і, відкидаючи ті, для яких /( > s.-, ви­ значити наступну поточну заявку. Саме ці поточні заявки й увійдуть до розв'язку задачі.

Тепер сформулюємо алгоритм розв'язування задачі про заявки: 1. Впорядкувати всі заявки за зростанням часу завершення

занять /;.

2.Взяти першу заявку і визначити її як поточну (j := 1).

3.Визначити

4.Якщо f: < st, то і-ту заявку визначити як поточну (у :- і).

5.Якщо і ^ п, то розглянути наступну заявку в послідовності упорядкованих за зростанням часу завершення занять (і := і + 1)

іперейти до п. 4.

6.Завершити алгоритм.

Як і в попередніх двох задачах, наведемо приклад реалізації основної частини описаного алгоритму мовою програмування без зайвих коментарів:

 

.

sort;

 

 

writeln(f_out, s[1], '-',f[1]);

 

 

j : = 1 ;

 

 

for і := 2 to n do

 

 

ifs[i]>f[j]

 

 

then begin

•".my,

 

writeln(f_out, s[i], '

 

j:=i;

 

 

end;

 

 

237

Оцінка ефективності виконання алгоритму задачі про заяв­ ки аналогічна визначенню її для неперервної задачі про рюкзак

0(п logri).

Критерії застосування жадібних алгоритмів

Як дізнатися, починаючи розв'язування задачі, чи дасть жадібний алгоритм оптимальний розв'язок? Загальних ре­ цептів не існує, але існують певні особливості, характерні для задач, що розв'язуються жадібними алгоритмами.

Для того щоб переконатися у можливості й доцільності ви­ користання жадібного алгоритму для розв'язання поставленої задачі, необхідно визначити, що цей алгоритм дасть у резуль­ таті оптимальний розв'язок. Для цього необхідно бути впевне­ ними у тому, що:

-всю задачу можна розбити на окремі етапи;

-кожний окремий етап задачі можна розв'язати із застосу­ ванням одного і того самого оптимізаційного алгоритму;

-кожний етап загальної задачі є незалежним, тобто його оп­ тимальний розв'язок не залежить від оптимальних розв'язків решти етапів і є складовою загального оптимального розв'язку всієї задачі.

Перші дві наведені ознаки притаманні як алгоритмам ди­ намічного програмування, так і жадібним алгоритмам. Однак між цими двома методами є суттєва різниця, і вона міститься у третій ознаці. Жадібні алгоритми та алгоритми динамічного програмування різняться тим, що:

-на кожному кроці жадібний алгоритм бере «найласіший шматок», а потім уже намагається зробити найкращий вибір серед тих, що залишилися, якими вони не були б;

-алгоритм динамічного програмування приймає рішення тільки після того, коли наперед будуть обчислені наслідки для всіх варіантів.

Підсумовуючи все сказане, можна сформулювати такий принцип жадібного вибору: послідовність локально оптималь­ них (жадібних) виборів дає глобально оптимальний розв'язок. Це і є основним у визначенні жадібного алгоритму, лише за умо­ ви наявності цього принципу можна беззаперечно стверджува­ ти, що для отримання оптимального розв'язку задачі слід засто­ сувати жадібний алгоритм. Принципу жадібного вибору варто приділити особливу увагу і детальніше його обговорити.

Як довести, що розроблений нами жадібний алгоритм дає оптимальний розв 'язок? Це не завжди тривіально, однак мож­ на спробувати побудувати доведення за такою схемою.

Спочатку слід довести, що жадібний вибір на першому кроці не відсікає шляхів до оптимального результуючого розв'язку,

238

тобто для цього визначеного на першому етапі розв'язку є інший, узгоджений з ним і не гірший за нього. Далі слід довес­ ти, що підзадача, яка виникає після жадібного вибору на пер­ шому кроці, аналогічна вихідній і т. д.

Нехай розглядається задача, процес розв'язання якої можна розбити на окремі етапи, і критерієм такого розбиття є вхідні дані. Наприклад, для задачі про центи - це номінали монет, для неперервної задачі про рюкзак - різновиди продуктів, для задачі про заявки - самі заявки. Якщо після визначення оптимального розв'язку на /г-му етапі можна з урахуванням його значення скоректувати вхідні дані задачі, відкинувши вже оброблені, і розв'язувати задачу далі як нову за тим самим алгоритмом, то можна стверджувати, що розроблено жадібний алгоритм і він дасть у підсумку правильний оптимальний результат.

Пояснимо ці міркування на прикладі попередньо розгляну­ тих задач.

Для задачі про центи на першому етапі була визначена мак­ симально можлива кількість монет найбільшим номіналом 25 і значення загальної суми S було зменшено на значення цього результату. Перед початком розв'язування другого етапу за­ гальної задачі ми оперуємо деякою сумою S і рештою монет, се­ ред яких немає монети номіналом 25. Але цієї монети могло не бути на першому етапі, та й початкове значення суми S могло бути таким, як після виконання першого .етапу. Тобто можна вважати, що наявність під задачі, яка розв'язувалася на першо­ му етапі, - це суто умовний факт, тобто її могло і не бути.

У неперервній задачі про рюкзак ситуація подібна: після того як було взято максимально можливу кількість першого продукту, загальна вага рюкзака або стала нульовою, або ж зменшилася на вагу взятого першого продукту. Подальша так­ тика розв'язування задачі не змінюється: беремо наступний продукт як перший, а щодо рюкзака, то можемо вважати, що його об'єм просто став меншим.

Остання задача про заявки розбивається на етапи відповідно до заданих заявок. Причому заявки розглядаються у такій послідовності, коли вказаний час завершення їх занять збіль­ шується. Відкинемо першу заявку, у якої час завершення за­ няття /х найменший. Чи можна вважати новою задачу, скорек­ товану так само, як і початкова? Безперечно, так, і довести це можна таким чином.

По-перше, решта заявок упорядковані за неспаданням часу завершення занять, тому наступна заявка має або такий самий час завершення, як і перша, або більший. Зауважимо, що у разі, коли час завершення цих двох заявок однаковий, то не­ має різниці, яку з них зараховувати до результуючої відповіді.

239

Визначивши першу заявку, ми фактично можемо змістити час початку занять: вони не можуть починатися раніше, ніж завер­ шиться перше заняття (/j).

По-друге, серед решти заявок (без першої) слід відкинути всі заявки з часом початку занять, який перевищує час завершен­ ня першої заявки ft. Таким чином, залишаться заявки, упоряд­ ковані за зростанням часу завершення занять, і одночасно такі, час початку яких більший за fv

Ми звели нову задачу до умови першої, визначивши першу заявку і відкинувши вхідні дані, які «відпрацювали» на пер­ шому етапі.

Жадібний алгоритм чи динамічне програмування? І жадібні алгоритми, і динамічне програмування базуються на власти­ вості оптимальності для підзадач, тому може виникнути ба­ жання застосовувати динамічне програмування там, де виста­ чило б і жадібного алгоритму, або навпаки, застосувати жадібний алгоритм до задачі, в якій він не дасть оптимального розв'язку.

Ці пастки можна продемонструвати на прикладі двох схо­ жих задач - неперервної задачі про рюкзак та її дискретної версії, яку ми розв'язували методом динамічного програмуван­ ня. Нагадаємо, що неперервна задача про рюкзак відрізняється від дискретної тим, що в рюкзак можна класти не цілі предме­ ти, а їхні частини.

Для прикладу розглянемо таку умову: максимальне заван­ таження рюкзака становить 55 кг, у який необхідно скласти три предмети відповідно вагою 10 кг і вартістю 60 одиниць, вагою 20 кг і вартістю 100 одиниць та вагою ЗО кг і вартістю 120 одиниць.

Розв'язавши цю задачу як неперервну жадібним алгорит­ мом, отримаємо відповідь: у рюкзаку буде розміщено повністю предмет вагою ЗО кг та предмет вагою 20 кг, а від предмета вартістю 60 одиниць буде взято лише половину. Таким чином, рюкзак буде заповнений повністю і вартість покладених у ньо­ го предметів становитиме 250 одиниць. Якщо тлумачити сфор­ мульовану задачу як дискретну, тобто за умови, що від пред­ метів не можна відділяти окремі частини, то відповідь буде та­ кою: у рюкзак буде покладено лише два предмети вартістю 120 та 100 одиниць загальною вагою 50 кг.

Отже, можна підбити підсумок: прийняття рішення щодо доцільності використання жадібного алгоритму для розв'язу­ вання заданої задачі залежить від уважного аналізу умови цієї задачі, можливості розбиття всієї задачі на незалежні під задачі і доведення факту отримання загального оптимального резуль­ тату.

240

Завдання

1.Розробити та реалізувати у вигляді програми алгоритм за­ дачі про центи.

2.Виконати завдання 1 для монет різного номіналу в кількості N ^ 10. Результат виконання програми вивести у файл.

3.Виконати завдання 1 для монет різного номіналу в кількості N ^ 100. Результат виконання програми вивести у файл.

4.Розв'язати завдання 2-3 методом динамічного програмування.

5.Розробити та реалізувати у вигляді програми алгоритм непе­ рервної задачі про рюкзак.

6.Виконати завдання 5 для різних продуктів кількістю ./V =% 10. Результат виконання програми вивести у файл.

7.Виконати завдання 5 для різних продуктів кількістю N < 100. Результат виконання програми вивести у файл.

8.Розв'язати завдання 6-7 методом динамічного програмування.

9.Розробити та реалізувати у вигляді програми алгоритм за­ дачі про заявки.

10.Виконати завдання 9 для різних заявок кількістю N < 10. Результат виконання програми вивести у файл.

11.Виконати завдання 9 для різних заявок кількістю N ^ 100. Результат виконання програми вивести у файл.

12.Розв'язати завдання 10-11 методом динамічного програму­ вання.

13. Проаналізувати результати виконання завдань 2-4, 6-8, 10-12.

 

Запитання для самоконтролю

 

1. Чим характеризується жадібний підхід до розв'язування задач?

 

2. Які графові задачі є прикладами задач, що розв'язуються

J

 

жадібними алгоритмами?

3.

Чи можна жадібні алгоритми вважати евристичними?

4.

Чи можна деякі евристичні алгоритми вважати жадібними? У чо­

 

му їх особливість?

5.Сформулюйте жадібний алгоритм розв'язування задачі про центи і обґрунтуйте коректність його використання у даному випадку.

6.Сформулюйте жадібний алгоритм розв'язування неперервної задачі про рюкзак і обґрунтуйте коректність його використання у даному випадку.

7.Сформулюйте жадібний алгоритм розв'язування задачі про за­ явки і обґрунтуйте коректність його використання у даному ви­ падку.

8.Як можна визначити, чи дасть жадібний алгоритм оптимальний розв'язок заданої задачі?

9.Як довести, що розроблений жадібний алгоритм дає оптималь­ ний розв'язок?

10.Як зробити правильний вибір між жадібним алгоритмом та ди­ намічним програмуванням?

241