You are on page 1of 8

 

 
 
 
 
 
 
 
 

 
 
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: ad­hoc 
 
 
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: ad­hoc 
 
   
 
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 for­petljom 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 for­petlja 
kategorija: ad­hoc 
 
 
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: ad­hoc 
 
 
   
 
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 i­ti 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: ad­hoc 
 
 
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 “ne­majorizirajućim” slučajevima 
prestizanje je moguće. 
 
potrebno znanje: matematička analiza problema, preprocessing 
kategorija: ad­hoc 
 
 
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: ad­hoc, sweep 

You might also like