310 likes | 542 Views
Uždavinys “ Egzaminas ”. Aut.: Linas Petrauskas. Kiekvienoje auditorijos eil ėje sėdi po vienodą skaičių studentų. Bet tuoj prasidės egzaminas. Studentai turi susėsti taip, kad kiekvienas sėdėtų priešais kito studento nugarą, o tarp vienoje eilėje sėdinčių būtų bent K laisvų vietų.
E N D
Uždavinys “Egzaminas” Aut.: Linas Petrauskas
Kiekvienoje auditorijos eilėje sėdi po vienodą skaičių studentų. Bet tuoj prasidės egzaminas. Studentai turi susėsti taip, kad kiekvienas sėdėtų priešais kito studento nugarą, o tarp vienoje eilėje sėdinčių būtų bent K laisvų vietų.
Kaip studentai turi persėsti, kad būtų tenkinami šie reikalavimai, o savo vietą tektų pakeisti kuo mažiau studentų? * Studentai negali prasilenkti ar pereiti į kitą eilę, * Auditorijos matmenys iki 200x100.
Pavyzdys, kai K = 1. (Savo vietą teks pakeisti mažiausiai 8 studentams.)
Pavyzdys, kai K = 2. (Savo vietą teks pakeisti mažiausiai 9 studentams. Šiuo atveju yra vienintelis būdas studentams susėsti.)
Iš anksto galime pasakyti, kurie studentai turės sėdėti toje pačioje (vertikalioje) eilėje:
Nesunkiai galime ir suskaičiuoti, kiek kiekvienam studentų “frontui” “kainuotų” pasislinkti iki kiekvienos galimos pozicijos (nepaisant kitų “frontų”) – ši kaina lygi toje pozicijoje nesėdinčių to “fronto” studentų skaičiui. (Nesijaudinkit – tai paprastoji dalis ;)
Tai čia aišku... Bet kaip spręsti uždavinį? Godi idėja...
...nebūtinai pateikia optimalų sprendinį. 8 studentai pakeičia vietą. 7 studentai pakeičia vietą.
* Teisingą atsakymą gautume išbandę visus variantus; * Perrinkimas užtrunka daug laiko. * Naudosime DINAMINĮ PROGRAMAVIMĄ.
Pastebėkime, kad jei žinotume, kur turi susėsti paskutinis studentų “frontas”, liktų išspręsti labai panašų, tik mažesnį uždavinį.
* Kita vertus, jei mokėtume spręsti mažesnį uždavinį, tai padėtų išspręsti didesnįjį. * Pradėsime nuo paties mažiausio uždavinio. * Paeiliui spręsime vis didesnį uždavinį, kol pagaliau rasime viso uždavinio sprendimą.
Paprasčiausias uždavinys – yra tik pirmasis “frontas” studentų ir tik viena vertikali eilė.
Sprendimas elementarus – visus susodinti į pirmą eilę. Tokio sprendimo “kaina” = 3.
Didesnis uždavinys – tai vienas studentų “frontas” ir dvi vertikalios eilės. Geriausio sprendimo “kaina” = 2.
Kai studentų frontų yra vienas, o eilės trys, vis tiek optimalu pirmąjį frontą sodinti antroje eilėje. Priešingu atveju būtų gaunama didesnė kaina. Geriausio sprendimo “kaina” = 2.
Pažymėkime f[i, j] – i-ojo fronto pasodinimo į j-ąją eilę kainą.(Lentelė viršuje.) Pažymėkime D[i, j] – optimalią pirmųjų i frontų susodinimo į pirmąsias j eilių kainą.
Mus dominantis atsakymas yra D[n, s], kur n yra frontų skaičius, o s – auditorijos eilių (vertikalių) skaičius. Jau išmokome optimaliai susodinti pirmojo fronto studentus bet kokiame kiekyje eilių: D[1, 1] := f[1, 1]; for i := 2 to s do D[1, i] := min(D[1, i-1], f[1, i]);
Pereikime prie didesnio uždavinio – nagrinėkime pirmuosius du studentų frontus. Jiems prireiks mažiausiai 3 vertikalių eilių. (K = 1)
Toks uždavinys taip pat turi tik vieną sprendinį: Geriausia pirmųjų 2 frontų susodinimo kaina pirmose 3 eilėse: D[2, 3] = D[1, 1] + f[2, 3] = 3 + 4 = 7
Kaip susodinti pirmuosius 2 frontus susodinti pirmosiose 4 vertikaliose eilėse. D[2, 4] = ? Renkamės iš 2 variantų: D[2, 4] = D[2, 3] = 7 ? D[2, 4] = D[1, 2] + f[2, 4] = 4 ? Renkamės pigesnį variantą, t. y. antrąjį. D[2, 4] = D[1, 2] + f[2, 4] = 2 + 2 = 4
Pagal tą pačią taisyklę renkamės ir toliau. D[2, 5] = D[2, 4], t. y. penkiose pirmosiose eilėse pirmuosius du frontus studentų optimalu susodinti taip pat kaip ir keturiose.
Pirmiesiems trims frontams studentų reikia mažiausiai 5 vertikalių eilių. (K = 1) Tokio susodinimo kaina: D[3, 5] = D[2, 3] + f[3, 5] = 9
Sodindami 3 frontus pirmosiose 6 eilėse renkamės iš 2 variantų: D[3, 6] = D[3, 5] = 9 ? D[3, 6] = D[2, 4] + f[3, 6] = 8? Renkamės pigesnį variantą, taigi, antrąjį. D[3, 6] = D[2, 4] + f[3, 6] = 4 + 4 = 8
Pagal tą patį algoritmą tęsiame ir randame uždavinio sprendimą: Optimali susėdimo kaina D[3, 7] = 8
Apibrendrinus: D[1, 1] := f[1, 1]; for j := 2 to s do D[1, j] := min(D[1, j-1], f[1, j]); for i := 2 to n do begin p := (i – 1) * (K + 1) + 1; D[i, p] := D[i - 1, p – k - 1] + f[i, p]; for j := p + 1 to s do D[i, j] := min(D[i, j – 1], D[i – 1, j – k – 1] + f[i, j]); end;
Lentelė f: Lentelė D:
Reikalingą studentų susodinimą randame grįždami nuo paskutiniojo langelio iki pirmosios eilutės. Lentelė D: