Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

HRVATSKO OTVORENO NATJECANJE IZ

INFORMATIKE
3. KOLO

OPISI ALGORITAMA
HONI 2011/2012 Zadatak AFRIKA
3. kolo, 17. prosinca 2011. Autor: Nikola Dmitrović

Očito je da će tražena količina novca koji se daruje biti ostatak pri djeljenju
ukupne količine novca i cijene jedne čokoladice.

Potrebno znanje: operator ostatka pri djeljenju dva broja (mod, %)

Kategorija: ad hoc

HONI 2011/2012 Zadatak OBRNI


3. kolo, 17. prosinca 2011. Autor: Adrian Satja Kurdija

Najprije, kako bismo riješili problem vodećih nula, s kraja zadanog broja
moramo uklanjati nulu dok god ona postoji. Drugim riječima, dok god je
zadani broj djeljiv s 10, dijelimo ga s 10, uklanjajući na taj način nulu s
njegovog kraja.

Potom treba ispisati znamenke danog broja u obrnutom redoslijedu. To


činimo tako da uzmemo posljednju znamenku danog broja, ispišemo je,
uklonimo tu znamenku s kraja danog broja i ponavljamo postupak dok god
ima znamenaka (tj. dok je dani broj veći od nule). Posljednju znamenku
broja dobivamo kao ostatak pri dijeljenju s 10, a uklanjanje posljednje
znamenke vršimo cjelobrojnim dijeljenjem broja s 10.

Potrebno znanje: rad sa znamenkama, for ili while petlja

Kategorija: ad hoc
HONI 2011/2012 Zadatak DIGITALNA
3. kolo, 17. prosinca 2011. Autori: Goran Gašić, Marko Ivanković

Zadatak jednostavno možemo riješiti sljedećim algoritmom:

1. Pomiči strelicu dolje dok ne pokazuje na kanal BLJTV1.


2. Pomiči strelicu i kanal gore dok nisu na prvom mjestu.
3. Pomiči strelicu dolje dok ne pokazuje na kanal BLJTV2.
4. Pomiči strelicu i kanal gore dok nisu na drugom mjestu.

Budući da se koraci 1 i 2 te 3 i 4 razlikuju samo u kanalu i mjestu, možemo


ih riješiti pozivom iste funkcije, kao u službenom rješenju.

Potrebno znanje: rad sa stringovima, for ili while petlja


Kategorija: ad hoc

HONI 2011/2012 Zadatak D’HONDT


3. kolo, 17. prosinca 2011. Autor: Nikola Dmitrović

Jedno od rješenja je implementacija svih zahtjeva iz zadataka onim redom


kako se navode. Za to trebamo jedan niz čiji će komponente imati dva dijela,
dio za oznaku stranke i dio za opisani količnik (record, struct).

Učitamo ukupan broj birača i broj stranaka te zatim onoliko puta koliko je
stranaka učitamo oznaku stranke i broj glasova koje je dobila istovremeno
provjeravajući je li stranka zadovoljava uvjet o prijeđenih 5% tj.
(glasovi/ukupno_biraci*100)>=5. Ako zadovoljava, tada u niz upišemo 14
vrijednosti koje imaju istu oznaku i količnik koji se dobije dijeljenjem broja
glasova te stranke i brojeva od 1 do 14.

Sortiramo niz po količnicima od većeg prema manjem te promatramo prvih


14 vrijednosti. Među njima treba pronaći koliko se puta pojavila oznake
pojedine stranke. Problem je kako pratiti koje su stranke uopće uzete u
razmatranje. To možemo postići kreiranjem stringa koji sadrži samo oznake
onih stranaka koje su prešle prag. Nakon što i taj string sortiramo lako ćemo
realizirati uvjet ispisa abecednim redom.

Potrebno znanje: niz, strukture, algoritam sortiranja, for petlja


Kategorija: ad hoc
HONI 2011/2012 Zadatak POGODAK
3. kolo, 17. prosinca 2011. Autor: Frane Kurtović

Prvo se trebamo odlučiti kako pamtiti kocku. Jedan mogući način je


“rastvoriti kocku” tako da sve strane položimo u ravninu na sljedeći način.
Na slici je rastvorena kocka koja se nalazi u
početnoj poziciji, odnosno u gornjem lijevom
polju matrice.

Pogledajmo kako izgleda rastvorena kocka kada ju otkotrljamo jedno polje u


desno (napravimo prvi potez).

Vidimo da je kotrljanje u desno jedino


promijenilo plavi redak i to tako da se plavi
redak kružno pomaknuo u lijevo.

Primijetite da kotrljanje u lijevo dovodi kocku


u isto stanje kao i kotrljanje u desno tri puta,
to će nam olakšati implementaciju ovog
rješenja.

Pogledajmo kako izgleda rastvorena kocka kada ju otkotrljamo jedno polje u


prema dolje. Na slici ćemo pokazati kotrljanje kocke iz početne pozicije (prva
slika).
Vidimo da je kotrljanje prema dolje jedino
promijenilo zelena polja i to tako da polja
2651 iz prve slike postaju 1265, tj. kružno
rotiramo ta polja u desno.
Sada bismo mogli implementirati simulaciju
kotrljanja kocke po svim poljima u matrici,
što bi dovelo do prevelike složenosti O(RS).
Simulaciju možemo ubrzati tako da brzo izračunamo sumu retka, te da brzo
izračunamo završno stanje kocke u retku.
Nakon točno četiri uzastopna rotiranja kocke u desno dolazimo ponovno u
isto stanje. To znači da krajnje stanje u retku možemo izračunati tako da
napravimo (S-1) mod 4 kotrljanja kocke u desno.

Da bismo izračunali sumu u tom retku još moramo izračunati sumu velikog
dijela retka koji se samo ponavlja s ciklusom duljine 4. Broj ciklusa K = (S-
1) div 4, gdje je div cjelobrojno dijeljenje.
Primijetite da je suma jednog ciklusa uvijek 14 jer se ciklus sastoji od dva
para suprotnih stranica, a suprotne stranice uvijek imaju sumu 7.
Dakle, suma velikog dijela retka iznosi 14K, a sumu ostatka izračunamo
simulacijom.

Konačna složenost rješenja je O(R).

Potrebno znanje: izrada vlastite strukture, uočavanje periodičnosti

Kategorija: ad hoc
HONI 2011/2012 Zadatak ROBOT
3. kolo, 17. prosinca 2011. Autor: Adrian Satja Kurdija

Ideja je pri svakom pomaku robota na brz način ažurirati traženi zbroj
udaljenosti od kontrolnih točaka.

Pretpostavimo da se robot pomaknuo udesno (na istok) iz točke (a, b) u


točku (a+1, b). Primijetimo da se udaljenost robota od bilo koje kontrolne
točke promijenila točno za 1 ili za -1. Naime, od svake kontrolne točke čija je
x-koordinata manja ili jednaka a robot se udaljio za 1, a svakoj kontrolnoj
točki čija je x-koordinata veća od a robot se približio za 1. Stoga, ako je f(a)
broj točaka čija je x-koordinata manja ili jednaka a, onda je N - f(a) broj
ovih drugih točaka, pa se ukupna udaljenost robota od kontrolnih točaka
promijenila za točno 1*f(a) + (-1)*(N - f(a)).

Analogne formule možemo izvesti za robotove pomake u drugim trima


smjerovima. Preostaje pitanje, kako brzo izračunati f(a), odnosno broj
kontrolnih točaka čija je x-koordinata manja ili jednaka a? (Trebat će nam i
slična funkcija g(a) za y-koordinate.) Jedan od načina je da držimo kontrolne
točke u dva niza: u jednom su sortirane po x-koordinati, a u drugome po y-
koordinati, te korištenjem binarnog pretraživanja u prvom nizu pronalazimo
poziciju prve kontrolne točke čija je x-koordinata veća od a, a ta je pozicija
upravo f(a) + 1. Analogno nalazimo g(a) u drugom nizu.

Složenost opisanog algoritma je O(N log N + M log N). Moguće je postići i


bolju složenost, na način da prije ikakvog micanja robota dinamički
izračunamo sve vrijednosti f(a) i g(a) - tzv. pretprocesiranjem.

Potrebno znanje: matematička analiza problema

Kategorija: ad hoc
HONI 2011/2012 Zadatak PLAĆE
3. kolo, 17. prosinca 2011. Autor: Ivan Katanić

Prvo je potrebno primjetiti da hijerarhijsku strukturu tvrtke možemo prikazati


stablom, tada podstablo nekog vrha(zaposlenika) predstavlja sve njemu
podređene zaposlenike.

Ako napravimo preorder DFS obilazak stabla dobiti ćemo listu svih vrhova u
stablu i to tako da je svako podstablo zapravo interval vrhova u listi:

L={}
OBILAZAK(u) :
dodaj u na kraj niza L
OBILAZAK(v) - za sve neposjećene v takve da
u stablu postoji brid (u,v)
Listu cijelog stabla dobiti ćemo pozivanjem obilaska iz korijena stabla:
OBILAZAK(1).

Sada nam je potrebna struktura podataka koja može povećati neki interval u
nizu L za određenu vrijednost i vratiti vrijednost nekog elementa u
određenom trenutku, a to je najjednostavnije postići sa interval(tournament)
stablom ili s Fenwickovim stablom(logaritamska struktura). Kako je svaka
operacija u navedenim strukturama složenosti O( log N ) ukupna složenost
rješenja je O( (N+M) log N ).

U priloženim kodovima je implementirano rješenje s Fenwickovim stablom.

Potrebno znanje: dfs obilazak stabla, strukture podataka

Kategorija: grafovi, strukture podataka


HONI 2011/2012 Zadatak TRAKA
3. kolo, 17. prosinca 2011. Autor: Gustav Matula

Uvjet koji je naveden u zadatku i kaže da nijedan automobil ne smije čekati


kod nijednog radnika lako se zapiše matematički. Dakle imamo automobil i i
radnika j. Ono što mora vrijediti jest činjenica da u trenutku kad radnik j
završi s automobilom i+1 radnik j+1 mora završiti s automobilom i (s tim da
radnik j+1 automobil i može dovršiti i prije). Ako automobil i+1 šaljemo t0
minuta nakon automobila i, mora vrijediti sljedeće:

Drugim riječima automobil i+1 mora proći radnike do j uključivo u barem


onoliko vremena koliko automobilu i treba za proći radnike do j+1 uključivo.

Ako označimo sumu T do radnika j sa Sj tada minimalni t0 za automobile i i


i+1 dobivamo kao:

Time već imamo ideju za brute-force rješenje (jednostavno petljom prođemo


kroz sve j i utvrdimo maksimum) i sumiramo te maksimume s FM-1SN-1 u
složenosti O(NM).

Za brže rješenje promotrimo izraz koji maksimiziramo. Budući da je indeks i


fiksan i da su svi faktori pozitivni možemo ga podijeliti s Fi+1. Označimo
omjer Fi/Fi+1 s x, dobivamo izraz f(x) = Sj+1x - Sj, dakle radi se o pravcu.
Kao što vidimo za svaki j koji zadovoljava već navedene granice dobivamo
po jedan pravac. U tom skupu pravaca tražimo onaj koji za neki x (preciznije
neki razlomak Fi/Fi+1) daje maksimalnu vrijednost.

Ovakva ideja inače je vrlo česta na natjecanjima, no budući da je neki možda


još nisu susreli, pojasnimo je malo detaljnije u općenitom slučaju.
Pogledajmo kako izgleda maksimum nekog skupa pravaca.
Radi se o nekoj izlomljenoj liniji koja ograđuje konveksnu regiju. Pravci koji
čine tu liniju s lijeva na desno sortirani su po nagibu. Također nijedan pravac
ne nalazi se iznad sjecišta prethodna dva (ova provjera algebarski je vrlo
slična CCW (counterclockwise) provjeri za tri točke). Ta dva zapažanja
dovoljna su za sljedeći algoritam izgradnje opisane linije:

Pravce sortiramo po nagibu rastuće, u slučaju jednakih po odsječku na y osi


rastuće. Ubacimo prva dva pravca na stog, i idemo redom po ostalim
pravcima. Dok promatramo neki pravac, izbacujemo prvi pravac sa stoga sve
dok se sjecište prva dva pravca na stogu nalazi ispod ili na pravcu koji
promatramo. Na stog zatim ubacimo taj pravac. Pravac koji je u stogu i-ti po
redu označavamo s fi(x).

Maksimum za neki x u takvom nizu pravaca nalazimo koristeći binarno


pretraživanje zbog činjenice da funkcija fi(x) po i raste pa pada (možete se u
to uvjeriti sa slike).

U ovom zadatku binarno pretraživanje nije bilo potrebno jer su sve


konveksne linije sadržavale malo pravaca, no koristi se u službenom
rješenju.

Konačni algoritam je složenosti O((N + M) log N) ili preciznije O(N log N +


M log H) gdje je H broj pravaca na konveksnoj liniji.

Postoji i alternativno rješenje koje izraz koji maksimiziramo promatra kao


vektorski produkt i koristi konveksne ljuske točaka.

Potrebno znanje: maksimum skupa pravaca


Kategorija: geometrija, optimizacija

You might also like