Professional Documents
Culture Documents
HRVATSKO OTVORENO NATJECANJE U INFORMATICI
3. kolo, 29. studenog 2014.
opisi algoritama
Zadatak TRŽNICA Autor: Ivan Paljak
Na svu sreću, Barica ima samo dvije mogućnosti kruške staviti u prvu košaru, a jabuke u
drugu (1. slučaj) ili kruške staviti u drugu košaru, a jabuke u prvu (2. slučaj). Analizirajmo
svaki od slučajeva:
1. Potrebno je prebaciti A jabuka iz prve košare i D krušaka iz druge košare. Vrijeme
potrebno u ovom slučaju jednako je A+D.
2. Potrebno je prebaciti B krušaka iz prve košare i C jabuka iz druge košare. Vrijeme
potrebno u ovom slučaju jednako je B+C.
Očevidno je najmanji mogući broj sekundi potreban za razvrstavanje voća jednak
min(A+D,B+C).
potrebno znanje: ulaz/izlaz, analiza slučajeva
kategorija: adhoc
Zadatak MATURA Autor: Nikola Dmitrović
Najprije valja pretvoriti dobivene parove (sat, minuta) u minute, i to na sljedeći način:
vrijeme = sat * 60 + minuta.
Sada proteklo vrijeme od početka ispita dobivamo jednostavnim oduzimanjem:
vrijeme_ucenikova_izlaska vrijeme_pocetka_ispita.
Ako je to vrijeme manje od 30 minuta, izlazak je nedozvoljen, tj. traženi je odgovor NE.
Slično, vrijeme do kraja ispita iznosi:
(vrijeme_pocetka_ispita + D) vrijeme_ucenikova_izlaska.
(U zagradi je najprije izračunato vrijeme završetka ispita). Ako je ovo manje od 15 minuta,
izlazak je nedozvoljen, tj. traženi je odgovor NE.
Ako se nijedan od gornjih dvaju slučajeva nije dogodio, izlazak je dozvoljen pa ispisujemo
DA.
potrebno znanje: osnovne operacije, naredba odlučivanja
kategorija: adhoc
Zadatak STROJOPIS Autor: Adrian Satja Kurdija
Jedno je moguće rješenje definirati osam nizova znakova (stringova) od kojih svaki sadrži
znakove pridružene jednom prstu. Prolazeći forpetljom po učitanome nizu znakova, u
unutrašnjoj petlji provjeravamo u kojem se od definiranih osam stringova nalazi trenutni
znak i povećavamo (za jedan) brojač pritisaka odgovarajućeg prsta. Ti brojači elementi su
niza od osam elemenata koji ćemo na kraju ispisati.
Za alternativno rješenje pogledajte priloženi kod strojopis.py.
potrebno znanje: rad s nizom znakova (string), ugnježđena forpetlja
kategorija: adhoc
Zadatak DOM Autor: Marin Tomić, Antonio Jurić
Uočimo da problem možemo predstaviti grafom: čvorovi će biti televizijski programi, a
parovi omiljenog i omraženog programa svakog umirovljenika usmjereni bridovi od
omraženog prema omiljenom programu.
U slučaju da je neki program omražen više umirovljenika (pa bi tada trebali i imati više
bridova koji izlaze iz njega svaki prema svojem omiljenom programu) dovoljno je pamtiti
samo jedan brid: onaj najmlađeg umirovljenika jer on ustaje i mijenja program u tom
slučaju.
Budući da je sada odabir mijenjanja programa jednoznačno određen, lako je doći do
rješenja: krećemo se po konstruiranom grafu krenuvši od zadanog programa P te brojimo
koliko smo trenutno programa promijenili (označimo taj broj s K) i koje smo programe već
gledali (prošli ih našim kretanjem u grafu).
Ako dođemo na program na kojem smo već bili, očito je da će se opet isti programi
ponavljati (kažemo da smo ušli u ciklus) pa ispisujemo 1.
Ako dođemo do programa koji nije omražen nikome (iz njega ne izlazi brid prema nekom
drugom programu), programi se više neće mijenjati pa je ukupni broj promjena programa
K (kretanja u grafu) naše rješenje.
potrebno znanje: teorija grafova, ciklusi
kategorija: adhoc
Zadatak SILUETA Autor: Ivan Paljak
Opisat ćemo najprije jedan naivan pristup. Mogli bismo, naprimjer, prvo naslikati obojanu
sliku. Odnosno, cijelu površinu svakog nebodera ispuniti znakovima ‘#’. Nakon bojanja,
slika prvog primjera iz teksta zadatka izgledala bi ovako:
........####
####....####
####..######
####..######
####..######
************
Sada nam još preostaje izbjeljivanje unutrašnjosti nebodera. Primijetimo da znak ‘#’
trebamo pretvoriti u znak ‘.’ ako se oko tog znaka (u 8 smjerova) ne nalazi znak ‘.’.
Provedbom ovog algoritma dobili smo traženu sliku.
Opseg možemo izračunati iz dobivene slike pažljivim brojanjem znakova ‘#’. Pribrojimo
opsegu za početak sve znakove ‘#’. Primijetimo sada da neki znakovi ‘#’ sudjeluju u dvije
stranice, dok neki takvi znakovi ne sudjeluju ni u jednoj. Opsegu tada treba dodati broj
znakova koji sudjeluju u dvije stranice i oduzeti broj znakova koji ne sudjeluju ni u jednoj.
Znakovi koje dodatno pribrajamo označeni su crvenom bojom, dok su znakovi koje
oduzimamo označeni plavom:
........####
####....#..#
#..#..###..#
#..#..#....#
#..#..#....#
************
Jasno je da su znakovi koje dodajemo ustvari gornji rubovi nebodera te imaju oblik:
## ##
#. ili .#
dok su znakovi koje oduzimamo dodirne točke dvaju nebodera te imaju oblik:
.# #.
## ili ##
Rješenja ovog kalibra, složenosti O(suma_površina), bila su dovoljna za osvajanje 50%
bodova na zadatku.
Neka maxh[i] označava maksimalnu visinu nekog nebodera koji proteže kroz iti stupac.
Elemente ovog niza možemo bezbolno izračunati u složenosti
O(N*(max{Ri}min{Li})).
Računanje opsega svodi se na linearan prolazak kroz niz maxh gdje konačnom rješenju
pribrajamo apsolutnu vrijednost razlike susjednih elemenata (vertikalne stranice) te
jedinicu za svaki stupac gdje je maxh[i] > 0 (horizontalne stranice). Sličnim postupkom
radimo i rekonstrukciju slike.
Ovakva implementacija bila je dovoljna za osvajanje svih bodova na zadatku.
potrebno znanje: analiza složenosti, implementacija
kategorija: adhoc
Zadatak HONI Autor: Adrian Satja Kurdija
Neka uređeni par (x, y) označava natjecatelja koji je osvojio x bodova na prvom kolu i y
bodova na drugom kolu.
Fiksirajmo nekog natjecatelja (a, b). Da bismo našli njegovo najbolje moguće mjesto, valja
izbrojiti natjecatelje (x, y) koji na ukupnoj listi sigurno pobjeđuju (a, b): njihov broj uvećan
za jedan traženo je najbolje mjesto natjecatelja (a, b).
Ako je x > a i y > b, natjecatelj (x, y) sigurno pobjeđuje (a, b). Ima li još natjecatelja koji ga
sigurno pobjeđuju? Nema! Ostali natjecatelji mogu nakon prvih dvaju kola biti ispred (a, b)
najviše za 600 bodova (jer ga barem na jednom kolu nisu pobijedili), pa ako svi oni na
trećem kolu osvoje 0 bodova, (a, b) ih dostiže ako osvoji 600 bodova. Treba dakle samo
izbrojiti natjecatelje (x, y) takve da je x > a i y > b.
Pronađimo sada najlošije moguće mjesto natjecatelja (a, b). Pretpostavimo da na trećem
kolu on osvaja 0 bodova. Koji ga natjecatelji (x, y) mogu na ukupnoj listi pobijediti? Jasno,
to ne mogu biti oni za koje je x < a i y < b jer i oni osvajaju 0 bodova. Pretpostavimo da svi
ostali natjecatelji (x, y) na trećem kolu osvajaju 600 bodova. Oni su barem na jednom kolu
imali više ili jednako bodova kao (a, b). Ako su tada imali jednako kao (a, b), a na
preostalom kolu izgubili od (a, b) za 600 bodova, nakon triju kola imat će jednak zbroj
bodova kao (a, b) pa ga ne pobjeđuju. U svim ga ostalim slučajevima pobjeđuju.
Rezimirajmo: u najlošijem scenariju za (a, b), natjecatelji (x, y) koji ga NE pobjeđuju su oni
za koje je x < a i y < b, te oni za koje je x = a, y = 0, b = 600 ili y = b, x = 0, a = 600. Njihov
broj oduzet od N 1 daje broj natjecatelja koji pobjeđuju (a, b), pa taj broj uvećan za jedan
daje najlošiju moguću poziciju natjecatelja (a, b) nakon prvih triju kola.
Zadatak se dakle svodi na brojenje parova (x, y) takvih da je x > a i y > b, kao i onih za
koje je x < a i y < b. Ako broj parova (x, y) spremimo u matricu na mjesto [x][y], trebamo
brzo pronaći zbroj nekog pravokutnika u toj matrici. To činimo tako da najprije dinamički
izračunamo zbrojeve za sve pravokutnike koji počinju u vrhu (0, 0) i onda njihovim
međusobnim oduzimanjem brzo računamo zbroj bilo kojeg pravokutnika.
Česte pogreške natjecatelja na ovome zadatku:
neki koji su koristili logaritamsku strukturu (Fenwickovo stablo) zaboravili su da ona
ne ide od 0 nego od 1,
mnogi nisu primijetili da natjecatelj (0, b) ne može prestići natjecatelja (600, b) iako
ga ovaj drugi “ne majorizira”. U svim drugim “nemajorizirajućim” slučajevima
prestizanje je moguće.
potrebno znanje: matematička analiza problema, preprocessing
kategorija: adhoc
Zadatak STOGOVI Autor: Ivan Katanić
Zamislimo stablo stogova takvo da svaki stog u zadatku odgovara putu do nekog vrha u
stablu od korijena stabla. Svakom vrhu će biti pridružen neki prirodan broj x, osim korijenu,
kojemu će biti pridružena nula. Svakoj oznaci stoga v će, dakle, biti pridružen i jedan vrh
stabla, nazovimo ga fv. Upravo broj u vrhu fv je broj na vrhu stoga v, a penjajući se do
korijena vidjeli bismo cijeli stog. Pritom, naravno, ignoriramo nulu u korijenu stabla.
Uvjerimo se da je to zaista moguće, na početku igre imamo jedan prazan stog, načinimo
stablo s vrhom 0. Kod kopiranja stoga v i dodavanja novog broja i jednostavno dodamo
novi vrh u stablo, u njega upišemo broj i te mu za roditelja postavimo fv.
Kod kopiranja stoga v i skidanja elementa s njegova vrha ćemo ispisati broj u vrhu fv te
novom stogu pridružiti roditelja od fv.
Jasno je da je stablasta struktura održana nakon svake operacije te da su sve operacije
konstantne složenosti.
No preostaje nam još moći efikasno odgovoriti na upit tipa c. Za početak primijetimo da su
su brojevi koji se stavljaju na stogove uvijek uzlazni, tj. niti jedna dva vrha u stablu neće
imati zapisan isti broj x u sebi. Tako je pitanje “koliko istih brojeva se nalazi u stogovima v i
w” jednako kao i pitanje “koliko istih vrhova, osim korijena, se nalazi na putu od korijena
do fv i na putu od korijena do fw”. Svi takvi vrhovi će biti u prvom dijelu puta od korijena do
fv/fw, jer jednom kad se putevi raziđu nikada više se neće susresti. Dakle dovoljno je
pronaći zadnji takav vrh te ispisati koliko se vrhova nalazi na putu od korijena do njega.
Taj vrh se još naziva i najniži zajednički predak u stablu (LCA) i postoje brojne metode za
njegovo pronalaženje. Najpopularnije rješenje je “skokovi duljina potencija broja 2” (za više
informacija pogledajte ovaj link
http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncest
or), složenosti O(N log N) za pretprocessinga te O(log N) po upitu.
Potrebno je još primjetiti da u ovom zadatku nemamo cijelo stablo za koje možemo na
početku izgraditi tablicu skokova, no to nije problem, pri dodavanju novog vrha (jedino
tada se stablo mijenja) izračunat ćemo sve njegove skokove u složenosti O(log N) budući
da su skokovi njegovih predaka već izračunati.
Ukupna vremenska i memorijska složenost rješenja je O(N log N).
Zadatak KAMIONI Autor: Mislav Bradač
Zamislimo pojednostavljenu verziju zadatka u kojoj imamo samo dva kamiona i jedan upit.
Definirajmo događaj kao par (id, t) koji nam označava da se kamion s indeksom id okreće
u vremenu t (tj. nakon t minuta od polaska).
Nakon izračuna događaja i njihovog sortiranja po vremenu obrađujemo jedan po jedan
događaj i pri tome za svaki kamion pamtimo u kojem trenutku se zadnji put okrenuo, na
kojoj poziciji se okrenuo i u kojem smjeru se kreće. Te informacije su nam dovoljne da za
svaki trenutak t izračunamo koji kamion se nalazi u gradu s manjim indeksom. Susret
detektiramo kada za neka vremena ti i ti+1 (vremena uzastopnih događaja) vrijedi slijedeće:
● ai < bi i ai+1 > bi+1 ili ai > bi i ai+1 < bi+1, ai grad u kojem se nalazi prvi kamion u
trenutku ti, bi grad u kojem se nalazi drugi kamion u trenutku ti.
Ova tvrdnja slijedi iz činjenice da dva pravca mogu imati najviše jedno sjecište ili se
potpuno preklapati (no neće se potpuno preklapati zbog napomene iz zadatka).
50% bodova na zadatku se moglo osvojiti ako svaki upit zasebno riješimo na gore opisani
način promatrajući događaje za samo dva kamiona za koje nas zanima broj susreta u
trenutnom upitu.
Kad riješimo zadatak za 50% bodova postaje nam jasno da ćemo za potpuno rješenje
zadatka na neki način morati riješiti više upita odjednom. Promotrimo sljedeći algoritam:
● upit pridijelimo samo jednom kamionu iz para
● izračunamo događaje svih kamiona te sortiramo događaje po vremenu
● obrađujemo događaje po redu i pri tome pamtimo za svaki kamion: u kojem
trenutku se zadnji put okrenuo, u kojoj poziciji se zadnji put okrenuo i u kojem
smjeru se kreće
● tijekom obrade događaja (id, t) kamiona s indeksom id za svaki upit pridijeljen tom
kamionu se pitamo nalazi li se drugi kamion iz para lijevo ili desno od njega u
vremenu t; primijetimo da još uvijek vrijedi uvjet susreta naveden u opisu rješenja
za 50% bodova iako promatramo relativni položaj kamiona iz upita tijekom obrade
događaja samo jednog kamiona iz para (jedino treba biti oprezan kod obrade
događaja nakon što vanzemaljci otmu neki kamion)
Neka je S suma svih Ki. Ako pridijelimo upit uvijek kamionu koji ima manji broj gradova u
ruti dolazimo do složenosti O(S sqrt S). Lako je dokazati složenost ako razdijelimo upite na
velike i na male (upit je velik ako oba kamiona iz para imaju više od sqrt S gradova u ruti,
inače je mali). Malih upita može biti M i za svaki mali upit moramo najviše sqrt S puta
određivati relativni položaj kamiona. Velikih kamiona (onih koji imaju više od sqrt S
gradova u ruti) može biti najviše sqrt S i za svaki od njih drugi kamioni iz upita mogu
najviše S puta određivati relativni položaj. Prema tome složenost obrade malih upita je
O(M sqrt S), a velikih O(S sqrt S) što vodi do ukupne složenosti O(S sqrt S).
Zadatak ima i alternativno rješenje iste složenosti koje dijeli kamione na one koji imaju više
od sqrt S gradova u ruti te za njih računa broj susreta sa svakim drugim kamionom i na
kamione koje imaju manje od sqrt S gradova u ruti te za njih računa samo one upite koji
nisu izračunati obradom velikih kamiona. Detaljnije o alternativnom rješenju možete
saznati u datoteci alternativno_kamioni.cpp.
potrebno znanje: analiza složenosti
kategorija: adhoc, sweep