Professional Documents
Culture Documents
HRVATSKO OTVORENO NATJECANJE U INFORMATICI
7. kolo, 7. ožujka 2015.
opisi algoritama
Zadatak DUET Autor:
Adrian Satja Kurdija
Ako je
A broj
ženskih natjecatelja u timu, očito je
12 A broj
muških natjecatelja.
Manji
od ovih dvaju brojeva traženi je broj dueta u dotičnome timu: ne može ih biti više jer će
nedostajati ženskih ili muških natjecatelja. Konačno je rješenje zbroj ovih minimuma
min(A, 12 A) za sva četiri tima. Alternativno rješenje u samo jednoj liniji Python koda
dano je u prilogu.
Potrebno znanje: osnovne naredbe
Kategorija : adhoc
Zadatak TABLICA Autor:
Adrian Satja Kurdija
Lako zaključujemo da valja ispisati 2R 1 redaka i 2S 1 stupaca. Ugnježđenom
forpetljom (vanjska bira redak, unutarnja bira stupac) ispisujemo znak po znak. Koji znak
valja ispisati? Ovisi o poziciji na kojoj se nalazimo. Ako smo u parnome retku (nultom,
drugom, četvrtom…), redak izgleda ovako: ++++ ..., a trenutni znak (plus ili minus)
ovisi o parnosti stupca. Ako smo pak u neparnome retku (prvom, trećem, petom…), redak
izgleda ovako: |.|.|.| ..., a trenutni znak (crta ili točka) ovisi o parnosti stupca.
Potrebno znanje: ugnježđena forpetlja
Kategorija : adhoc
Zadatak TETA Autor:
Marin Tomić
Cijene jela koja nisu na meniju možemo samo pribrojiti u konačno rješenje i maknuti ih s
pladnja. Nakon toga, pogledamo koja sve jela s menija su preostala na pladnju i uzmemo
po jedan primjerak od svakog. Ako je zbroj njihovih cijena veći od cijene menija, platit
ćemo meni i maknuti jela s pladnja, a inače ćemo platiti svako jelo zasebno i maknuti ih s
pladnja.
Za detalje pogledajte izvorni kod.
Potrebno znanje: whilepetlja
Kategorija : pohlepni algoritmi
Zadatak KRIZA Autor:
Ivan Paljak
Naivan pristup svodi se na simulaciju svakog pokušaja otključavanja vrata. Budući da Sizif
pri nailasku na svaka vrata mora na drugu stranu prebaciti najviše N ključeva, a posjetio je
ukupno K vrata, složenost takvog algoritma je O(N*K) što donosi 40% bodova na zadatku.
Valja primijetiti da dolaskom do i
tih vrata najdesniji ključ na privjesku otključava vrata i1
te da se između ključeva s oznakama i
i
j
uvijek nalazi konstantan broj drugih ključeva.
Tada možemo u O(1) saznati koliko je pogrešnih ključeva Sizif stavio u vrata s nekom
fiksnom oznakom i
. To nas dovodi do rješenja složenosti O(K) koja donose 60% bodova
na zadatku.
Na kraju, valjalo je primijetiti da se različita stanja ključeva na privjesku nužno ulaze u
ciklus duljine N. Popunimo li neki niz A[]
, gdje A[i]
govori koliko je pogrešnih ključeva Sizif
stavio od prvih do itih vrata (za
i
<=
N
), možemo u O(1) odgovoriti na traženo pitanje.
Popunjaanje niza A[] radimo u složenosti O(N) , što donosi 100% bodova na zadatku.
Dodatno je trebalo pripaziti na prvo otključavanje, odnosno prijelaz iz početnog stanja u
stanje nakon prvih vrata koje može, ali i nemora biti dio ciklusa opisanog u prošlom
odlomku. Također, valja primijetiti kako rješenja mogu izači van opsega 32bitnog broja.
Potrebno znanje: Ciklusi
Kategorija : adhoc
Zadatak ACM Autor:
Adrian Satja Kurdija
Rješenje koje na sve moguće načine dijeli niz zadataka na tri dijela presporo je. Zadatak
stoga rješavamo dinamičkim programiranjem. Stanje je opisano zadatkom na kojem se
trenutno nalazimo i članom tima (prvi, drugi ili treći) kome je dodijeljen prethodni zadatak.
U prijelazu biramo hoćemo li i ovaj zadatak dodijeliti istom članu tima ili ćemo prijeći na
sljedećeg člana. U priloženom kodu dinamika je implementirana rekurzivno, koristeći
memoizaciju. Naravno, moguća je i iterativna implementacija.
Potrebno znanje: dinamičko programiranje
Kategorija : dinamika
Zadatak JANJE Autor:
Ivan Paljak
Primijetimo najprije da svaku sliku možemo predstaviti grafom gdje broj čvorova odgovara
broju površina koje je potrebno ispuniti, a dva su čvora povezana ako su odgovarajuće
dvije površine susjedne. Svakom čvoru grafa potrebno je pridružiti jednu od K boja na
način da su dva susjedna čvora različito obojena i iskorištene su maksimalno 3 različite
boje.
Dobar dio službenih test podataka sadržavao je dovoljno mali broj K i sliku sa dovoljno
malim brojem čvorova tako da su naivne implementacije gore opisanog postupka nosile do
50% bodova na zadatku.
neka j(n), d(n)
i
t(n
) redom označavaju broj načina na koji je moguće ntu sliku obojiti
točno jednom, točno dvije i
točno tri različite boje. Tada je konačno rješenje jednako
j(n)*K + d(n)*K*(K 1)/2 + t(n)*K*(K1)*(K2)/6. Na svim silkama vrijedi j(n) = 0 pa bojenje
jednom bojom možemo ignorirati. Ukoliko je sliku moguće obojiti u dvije boje, tada je d(n)
= 2. Ostaje problem određivanja t(n).
Sve slike osim gusjenice, piramide i trampolina predstavljamo grafom koji ima dovoljno
mali broj čvorova v da će određivanje broja t(n)
u složenosti
O(3^
v
) biti dovoljno brzo.
Koristeći ovaj pristup mogli ste osvojiti 75 bodova na zadatku.
Valja istaknuti kako je brojeve j(n),
d(n) i
t(n) bilo moguće izvesti na papiru za svaku sliku
posebno. Mnogi natjecatelji su na taj način i pristupili zadatku, ali su nerijetko napravili
neku pogrešku u izračunu.
Spomenute 3 slike (gusjenica, piramida i trampolin) valja detaljnije analazirati. Primjerice,
možemo primijetiti kako ćemo ispunom drugog reda piramide jednoznačno odrediti ostatak
piramide. Slične dosjetke na slikama gusjenice i trampolina ostavljamo čitateljici za vježbu.
Potrebno znanje: grafovi, kombinatorika
Kategorija : adhoc
Zadatak PROSJEK Autor: Ivan Katanić
Direktno odgovaranje na pitanje koji je najveći mogući prosjek je težak problem, no što ako
umjesto toga pokušamo odgovoriti na pitanje je li najveći mogući prosjek veći ili jednak
nekoj vrijednosti P. Ako to uspijemo onda zadatak možemo rješiti binarnim pretraživanjem
po vrijednosti P.
I taj problem izgleda teško, no primjetimo ovo: ako svim brojevima u nizu oduzmemo X,
tada će se i prosjek svih podnizova smanjiti za točno X. Sada možemo svim brojevima u
nizu oduzeti vrijednost P i ono što nas zanima jest postoji li podniz s prosjekom većim ili
jednakim 0. Taj problem je jednostavniji jer je to ekvivalentno pitanju postoji li podniz sa
sumom većom ili jednakom nuli.
Ako izračunamo prefiks sume S ulaznog niza, tada je suma nekog podniza [a, b] jednaka
S[b] S[a1]. Za svaki mogući b možemo se pitati postoji li a takav da je S[b] S[a1] >= 0
tj. S[b] >= S[a1] te, ne zaboravimo uvjet na minimalnu duljinu podniza, da je ba+1 >= K tj.
a <= b+1K.
Prolazeći vrijednostima granice b slijeva na desno u posebnoj varijabli možemo držati
najmanju dosad viđenu vrijednost S[a1] i provjeravati zadovoljava li ona uvjet za trenutni
b, ako zadovoljava pronašli smo podniz s prosjekom većim ili jednakim P.
Pri svakom povećanju vrijednosti b za 1 točno jedna nova vrijednost za a dolazi u obzir i to
je a = bK+1. Održavanje varijable onda radimo tako da pri svakom povećanju vrijednosti
provjerimo je li S[bK] manji od trenutne najmanje vrijednosti te ju osvježimo ako jest.
Za detalje pogledati priloženi kod.
Potrebno znanje: binarno pretraživanje, matematika
Kategorija : razno
Zadatak POLICE Autor:
Mislav Bradač
Prvo što moramo provjeriti je postoji li prazno mjesto na bilo kojoj polici. U slučaju da ne
postoji provjeravamo jesu li sve knjige na pravom položaju, ako nisu, nema rješenja te
ispisujemo 1, inače je rješenje 0.
Pogledajmo kako riješiti test podatke vrijedne 50% bodova u kojima za svaku knjigu vrijedi
da je na istoj polici na početku i na kraju. Police dijelimo u tri kategorije:
1. polica na kojoj na početku postoji prazno mjesto
k broj knjiga na polici
lis najdulji podniz knjiga koji su na početku u dobrom relativnom poretku
svaku knjigu koja se ne nalazi u lisu moramo podići da bi posložili knjige
na toj polici, tj. treba nam k lis
dizanja
primijetimo da uvijek guranjem knjiga možemo osloboditi poziciju na polici
na koju moramo staviti knjigu prije nego ju podignemo
lis lako nalazimo u O(k log k) poznatim algoritmom za traženje najdužeg
rastućeg podniza
2. polica je puna, ali sve su knjige na svome mjestu
za police ove vrste nam ne treba nijedno dizanje
3. polica je puna, ali postoji knjiga koja nije na svom mjestu
jednu knjigu koja se ne nalazi u lisu prebacimo na prazno mjesto na nekoj
drugoj polici
posložimo ostale knjige na polici u pravi poredak, pri tome ne dižući knjige
koje se nalaze u lisu
vraćamo knjigu koju smo prebacili na neku drugu policu na pravu poziciju
za police ove vrste nam treba k lis + 1 podizanje
U test podacima u kojima postoje knjige koje se na početku i na kraju ne nalaze na istoj
polici podijelit ćemo police u 2 kategorije:
1. police na kojima su knjige koje se nalaze na početku i na kraju na toj polici te se
svaka knjiga koja se na kraju nalazi na toj polici nalazila i na početku
ove police rješavamo na isti način na koji smo rješavali i u test podacima
vrijednim 50% bodova
2. ostale police
Sada nam preostaje riješiti drugu kategoriju polica. Izgradimo neusmjereni graf u kojem su
police čvorovi. Dva čvora su povezana ako postoji knjiga koja se na početku nalazi na
polici koju predstavlja prvi čvor, a na kraju na polici koju predstavlja drugi čvor.
Sada ćemo svaku komponentu tog grafu riješiti posebno te ćemo ponovo uvesti dva
slučaja:
1. sve police u komponenti su na početku pune
izgradimo sada usmjereni graf ove komponente tako da usmjerimo brid iz
čvora u kojeg dolazi knjiga (čvor u kojem je knjiga na kraju) u čvor iz kojeg
dolazi knjiga (čvor u kojem je knjiga na početku)
primijetimo da će svaki čvor imati isti indegree i outdegree te da možemo
izgraditi eulerov ciklus
jednu knjigu iz nekog čvora A koja se ne nalazi na istoj polici na početku i
na kraju stavljamo na prazno mjesto na neku policu koja ima slobodno
mjesto u tom trenutku
krećemo iz čvora A i krećemo se eulerovim ciklusom, kad pređemo iz čvora
A u čvor B prebacimo knjigu iz čvora B u čvor
A
tijekom obilaska eulerovog ciklusa u trenutku kada neka polica ima
slobodno mjesto knjige koje se na toj polici nalaze na početku i na kraju
stavljamo u dobar relativni poredak to radimo na način opisan u prvoj
kategoriji u rješenju za 50% bodova
sum_k broj knjiga na policama u toj komponenti
sum_lis suma lis
ova pojedinih polica te komponente
treba nam sum_k sum_lis + 1 podizanje da riješimo ovu komponentu
primijetimo da uopće ne trebamo graditi eulerov ciklus jer se od nas ne traži
rekonstrukcija rješenja
2. postoji polica u komponenti koja na početku nije potpuno puna
izaberimo neki čvor koji ima veći indegree od outdegreea te neki čvor koji
ima veći outdegree od indegreea te dodamo dummy brid između ta dva
čvora
ovaj postupak ponavljamo sve dok postoje takvi čvorovi
izgradimo eulerov ciklus te krenemo od čvora koji ima prazno mjesto na
početku, ako prođemo pravim bridom prebacujemo knjigu, ako prođemo
dummy bridom ništa ne prebacujemo
važno je primijetiti da će uvijek postojati prazno mjesto u čvoru u kojem se
nalazimo čak i ako smo u taj čvor došli dummy bridom, to vrijedi zbog
činjenice da ako polica ima veći outdegree od indegreea onda je broj
slobodnih mjesta na početku na toj polici veći jednak od razlike outdegreea i
indegreea
knjige koje su na istoj polici na početku i na kraju rješavamo na isti način
kao i u prethodnom slučaju
treba nam sum_k sum_lis podizanja da riješimo ovu komponentu
Ukupna složenost algoritma je O(N * M * log M).
Potrebno znanje: dfs, longest increasing subsequence
Kategorija
: kombinatorika, grafovi