You are on page 1of 10

HRVATSKO OTVORENO NATJECANJE IZ

INFORMATIKE 2013/2014

3. KOLO

OPISI ALGORITAMA
HONI 2013/2014 Zadatak ZDRAVKO
3. kolo, 7. prosinca 2013. Autor: Marin Tomić

Najmanji broj tužbi koje Zdravko može podići protiv nas, a da ih bude više
od N jest N+1. Ako izgubimo N+1 tužbu moramo platiti C*(N+1) kunu.

Potrebno znanje: naredbe ulaza i izlaza, osnovna aritmetika

Kategorija: rimsko pravo

HONI 2013/2014 Zadatak ULET


3. kolo, 7. prosinca 2013. Autor: Adrian Satja Kurdija

Brojeve na ulazu možemo učitati i kao brojeve i kao stringove. Ako ih


učitamo kao brojeve, valja iz tih brojeva znati izvući znamenke stotica,
desetica i jedinica. Za bilo koji prirodan broj B formule su sljedeće:

znamenka_jedinica = B mod 10
znamenka_desetica = (B div 10) mod 10
znamenka_stotica = (B div 100) mod 10

Ne preporučuje se učenje ovih formula napamet; one se lako nauče s


razumijevanjem ako je poznato da dijeljenje (div) broja s 10 otkida od
njega posljednju znamenku, a modanje (mod) broja s 10 daje njegovu
posljednju znamenku.

Budući da je B troznamenkast, postoji i jednostavnija formula za


znamenku stotica: B div 100.

Kada smo izvukli ove znamenke, valja ih usporediti sa znamenkama


očekivanih brojeva (365 i 666) i povećati traženo rješenje za 1 svaki put
kada nađemo razliku.

Jednostavnije je učitati brojeve na ulazu kao stringove; u tom slučaju ih


možemo spojiti u jedan string te for-petljom izbrojiti na koliko se pozicija
taj string razlikuje od stringa “365666”.

Potrebno znanje: rad sa znamenkama

Kategorija: ad hoc

HONI 2013/2014 Zadatak RIJEČI


3. kolo, 7. prosinca 2013. Autor: Marin Tomić

Ako bismo pokušali simulirati Mirkov postupak, prekoračili bismo i


vremensko i memorijsko ograničenje, jer riječi koje Mirko dobiva na ekranu
čak i za male K mogu imati nekoliko stotina tisuća (ili čak milijuna)
znakova. Zato nećemo simulirati Mirkov postupak nego ćemo samo
računati broj slova A i B na sljedeći način:
● na početku je broj_A = 1, a broj_B = 0
● u jednom koraku dobijemo po jedno slovo A za svako B koje smo do
sada imali, i po jedno B za svako A i za svako B koje smo do sada
imali, dakle novo_A = broj_B, a novo_B = broj_A + broj_B

Potrebno znanje: for-petlja, računanje


Kategorija: for-petlja

HONI 2013/2014 Zadatak OKVIR


3. kolo, 7. prosinca 2013. Autor: Adrian Satja Kurdija

Najlakše je najprije ispuniti cijelu šahovnicu dimenzija (U + M + D) x (L +


N + R) znakovima # i ., a tek potom u nju upisivati Mirkovu križaljku. Za
oba ova postupka potrebna je dvostruka for-petlja koja ide redom po
poljima matrice (ili podmatrice).

Što se tiče ispunjavanja šahovnice, polje (i, j) bit će # ovisno o tome je li i


+ j parno ili neparno. Što se tiče upisivanja križaljke, polje (i, j) zadane
Mirkove križaljke iz ulaza upisat ćemo u polje (U + i, L + j) naše
šahovnice.

Potrebno znanje: rad s matricom

Kategorija: ad hoc

HONI 2013/2014 Zadatak REČENICE


3. kolo, 7. prosinca 2013. Autor: Marin Tomić

Budući da se u zadatku jamči da će rješenje postojati i biti manje od


1000, možemo jednostavno isprobati ubacivanje svi brojeva od 1 do 999 u
rečenicu i provjeravati je li ona moguće rješenje.
Da bi rečenica s ubačenim brojem x bila moguće rješenje mora vrijediti:
duljina imena broja x + suma duljina riječi u rečenici = x

Sada nam je jedini problem napraviti funkciju kojom ćemo imenovati


brojeve. To možemo učiniti na sljedeći način:
● napravit ćemo tri niza, posebni[], desetice[], stotice[]
● niz posebni će sadržavati imena brojeva od 1 do 19, npr.
posebni[11] će biti “jedanaest”
● niz desetice će sadržavati imena desetica, npr. desetice[7] će biti
“sedamdeset”
● isto tako, niz stotice će sadržavati imena stotica, npr. stotice[3] će
biti “tristo”
● sada imenovanje brojeva implementiramo kako je opisano u tekstu
zadatka

Pseudokod:
imenuj(x)
odgovor = ‘’
ako je znamenka stotica od x različita od 0:
odgovor = odgovor + stotice[znamenka stotica od x]
izbaci znamenku stotica iz x
ako je x između 1 i 19:
odgovor + odgovor + posebni[x]
inače:
ako je znamenka desetica od x različita od 0:
odgovor = odgovor + desetice[znamenka desetica od x]
ako je znamenka jedinica od x različita od 0:
odgovor = odgovor + jedinice[znamenka jedinica od x]

Za implementacijske detalje pogledajte kodove.

Potrebno znanje: rad sa stringovima


Kategorija: brute-force algoritmi, stringovi

HONI 2013/2014 Zadatak KOLINJE


3. kolo, 7. prosinca 2013. Autor: Adrian Satja Kurdija

Ljudi od 1 do N dobit će, redom, B1X, B2X, …, BNX kilograma šunke, za


neki X. Mi trebamo naći takav X da poredak bude ispravan; iz njega je lako
izračunati ukupan broj podijeljenih kilograma.

Želimo da vrijedi A1 + B1X ≥ A2 + B2X ≥ … ≥ AN + BNX.

Analizirajmo prvu nejednakost; ostale se analiziraju potpuno analogno. Iz


A1 + B1X ≥ A2 + B2X slijedi
(B1 - B2)X ≥ A2 - A1.

Željeli bismo podijeliti ovu nejednakost sa B1 - B2 kako bi na lijevoj strani


ostao samo X. Moramo međutim biti pažljivi!

Ako je B1 - B2 = 0, ne možemo dijeliti nego se nejednakost svodi na 0 ≥


A2 - A1. U ovom slučaju, ako je zapravo A2 - A1 > 0, ispisujemo -1 jer
imamo kontradikciju. Inače nejednakost “štima” pa prelazimo na sljedeću.

Ako je B1 - B2 ≠ 0, smijemo dijeliti, ali dijeljenje negativnim brojem


mijenja znak nejednakosti pa dobivamo ili X ≥ (A2 - A1) / (B1 - B2) ili X ≤
(A2 - A1) / (B1 - B2). U jednom slučaju dobili smo donju, a u drugom
slučaju gornju granicu za X.
Ponavljanjem ovog postupka za svih N - 1 nejednakosti sakupili smo neke
donje i neke gornje granice za X. Od svih donjih granica zanima nas samo
najveća (jer ona povlači sve ostale), a od svih gornjih granica zanima nas
samo najmanja (jer povlači sve ostale). Ako između tih dviju granica
postoji neki broj, tj. ako je donja manja ili jednaka gornjoj, rješenje
postoji: kao X možemo uzeti npr. prosjek donje i gornje granice. Inače
nema rješenja.

Zadatak je moguće riješiti i binarnim pretraživanjem; detalje ostavljamo


čitateljici za vježbu.

Potrebno znanje: matematička analiza problema, osnove matematičkih


nejednakosti

Kategorija: ad hoc

HONI 2013/2014 Zadatak PAROVI


3. kolo, 7. prosinca 2013. Autor: Marin Tomić

Budući da se radi o vrlo velikim brojevima, očigledno je da računanje


udaljenosti za svaki par pojedinačno neće biti dovoljno brzo. No, svejedno,
napravimo to na jedan vrlo specifičan način.

Nećemo prolaziti po svim brojevima pomoću dvije ugniježdene petlje, nego


ćemo napraviti funkciju f(prefiks1, prefiks2, suma) koja će ih graditi
znamenku po znamenku.

Npr. par (32, 1689) bi bio izgrađen dodavanjem redom znamenki (0, 1), (0,
6), (3, 8), (2, 9).

Funkcija f izgledala bi ovako:

f(prefiks1, prefiks2, suma):


ako su prefiksi izgrađeni do kraja, vrati suma
neka (x, y) prolazi po svim mogućim parovima znamenki:
ako možeš dodati x na prefiks1 i y na prefiks2:
pozovi f(prefiks1 * 10 + x, prefiks2 * 10 + y, suma + |x – y|)

Ovo rješenje nije ništa brže od rješenja koje koristi dvije petlje, no može
se popraviti. Prvo ćemo se riješiti parametra suma iz funkcije.

Napraviti ćemo funkciju num(prefiks1, prefiks2) koja za dane prefikse prvog


i drugog broja računa na koliko načina možemo "završiti" ova dva broja.

num(prefiks1, prefiks2):
ako su prefiksi izgrađeni do kraja, vrati 1

rj = 0
neka (x, y) prolazi po svim mogućim parovima znamenki:
ako možeš dodati x na prefiks1 i y na prefiks2:
rj = rj + num(prefiks1 * 10 + x, prefiks2 * 10 + y)

vrati rj

Sada funkciju f možemo preoblikovati da izgleda ovako:

f(prefiks1, prefiks2):
ako su prefiksi izgrađeni do kraja, vrati 0

rj = 0
neka (x, y) prolazi po svim mogućim parovima znamenki:
ako možeš dodati x na prefiks1 i y na prefiks2:
rj = rj + num(prefiks1 * 10 + x, prefiks2 * 10 + y) * |x – y|
rj = rj + f(prefiks1 * 10 + x, prefiks2 * 10 + y)

vrati rj

Jedino što sad valja primijetiti jest da za provjeru možemo li dodati


znamenku x na prefiks ne moramo znati cijeli prefiks, već nam je dovoljno
za prefiks znati koju mu po redu znamenku trenutno dodajemo, te je li se
taj prefiks ikada razlikovao od gornje ili donje granice intervala.
To nas dovodi do rješenja primjenom dinamičkog programiranja složenosti
O(duljina broja * broj mogućih znamenki^2).
Za detalje pogledajte izvorni kod.

Potrebno znanje: dinamičko programiranje


Kategorija: dinamičko programiranje

HONI 2013/2014 Zadatak ODAŠILJAČI


3. kolo, 7. prosinca 2013. Autori: Matija Milišić, Antun Razum

Promatrajmo dio grada između neke dvije zgrade, taj interval označimo sa
[X, Y]. Za početak zanemarimo odašiljače desno od tog intervala. Svaki
odašiljač pokrit će neki dio [Z, Y], dok će lijevi dio [X, Z] biti nepokriven.
Dovoljno je, dakle, naći odašiljač koji ima najmanji Z, nazovimo ga ZL.

Slično zaključujemo za odašiljače desno od tog intervala. Tada će dio [X,


Z] biti pokriven, a dio [Z, Y] nepokriven. Tu moramo naći odašiljač koji ima
najveći Z, nazovimo ga ZD.

Kada za interval neki [X, Y] nađemo te dvije koordinate, ZL i ZD,


pokrivenost intervala računamo kao: Y - X - max {0, ZL - ZD}. Zadatak
sada možemo rastaviti na dva dijela: prvi će za svaki interval izračunati
ZL, a drugi na sličan način ZD.

Sada ćemo objasniti kako izračunati ZL. Možemo primijetiti da nam je u


tom slučaju za svaki odašiljač dovoljno promatrati samo dio signala koji se
prostire od desno od njega.

Proći ćemo kroz sve zgrade s lijeva na desno. Pritom ćemo održavati
strukturu u kojoj će se nalaziti neki od odašiljača sa zgrada koje smo već
prošli. Odašiljači će u strukturi biti poredani rastuće po svojoj apscisi. U
strukturi svakom će odašiljaču biti pridružena točka na X osi koja
označava mjesto od kojeg počinje pokrivenost tim odašiljačem ako se
uzmu u obzir zgrade koje smo do sada prošli (pokrivenost se prostire od te
točke na desno).
Sada ćemo pokazati bitno svojstvo strukture. Za odašiljač O označimo s
XO njegovu apscisu, s HO visinu, a s TO njegovu pridruženu točku, točnije
apscisu te točke. Definirajmo uz to i predikat bolji. Za dva odašiljača A i B
kažemo da je A bolji od B ako je TA < TB. Pretpostavimo sada da se u
strukturi nalaze dva odašiljača: A i B, za koje vrijedi XA < XB. Ako vrijedi
HA <= HB odašiljač B možemo izbaciti jer je A bolji. Pretpostavimo, dakle,
dodatno da vrijedi HA > HB. Ako vrijedi TA < TB, odašiljač B možemo
izbaciti, jer će A uvijek biti bolji.

Uzevši ovo svojstvo u obzir dobivamo sljedeće posljedice: visine odašiljača


u strukturi bit će padajuće i apscise pridruženih točaka bit će rastuće.

Sada lagano možemo osmisliti algoritam koji primjenjujemo za svaku


zgradu na koju naiđemo (dok prolazimo kroz njih s lijeva na desno). Prije
svega izbacimo sve odašiljače s kraja strukture koji su jednake ili manje
visine od trenutne zgrade. Ukoliko se sada na trenutnoj zgradi nalazi
odašiljač, dodamo ga u strukturu te je ZL za ovaj interval jednak X (apscisi
odašijača trenutne zgrade). Ako trenutna zgrada nema odašiljač,
promatramo zadnja dva odašiljača iz strukture. Sada ažuriramo njihove
pridružene točke (možda se mijenjaju nakon dodavanja posljednje zgrade).
Ukoliko posljednji odašiljač nakon ažuriranja ne zadovoljava svojstvo
strukture (TB > TA, gdje je A pretposljednji, a B posljednji odašiljač u
strukturi) izacujemo ga iz strukture. Ovaj postupak ponavljamo sve dok
možemo (tj. dok posljednji ne zadovoljava svojstvo strukture) uvijek
iznova ažurirajući pridruženu točku pretposljednjeg odašiljača.

Možemo primijetiti da nećemo morati ažurirati pridružene točke ostalih


odašiljača u strukturi nakon što smo završili ovaj postupak za neku zgradu
jer se one ne mijenjaju. Pretpostavimo suprotno, imamo dva odašiljača: A
i B, za koje vrijedi XA < XB, HA > HB i TA >= TB, te A treba ažurirati, a B ne
treba. Napravimo pravac PA kroz točke (XA, HA) i (TA, 0) te pravac PB kroz
točke (XB, HB) i (TB, 0). Posljednji uvjet znači da trenutni zid siječe PA i ne
siječe PB. Međutim, to je nemoguće jer bi onda B narušavao svojstvo
strukture, tj. ne bi vrijedio treći uvjet TA >= TB.

Kada prođemo kroz sve zgrade s lijeva na desno vrlo sličan postupak
ponovimo i sa suprotne strane te time dobivamo nizove ZL i ZD iz kojih
znamo konstruirati rješenje.
U rješenju ovog zadatka prolazimo dva puta kroz sve zgrade održavajući
strukturu koja može biti implementirana kao stog. Svaki korak prolaska
kroz zgrade amortizirane je konstatne složenosti jer kada prođemo kroz
sve zgrade svaki ćemo odašiljač točno jednom ubaciti i izbaciti iz
strukture. Budući da su operacije na stukturi koje koristimo konstatne
složenosti, složenost cjelokupnog rješenja je linearna tj. O(n), gdje je n
broj zgrada.

Potrebno znanje: matematika, amortizirana složenost


Kategorija: ad hoc

You might also like