You are on page 1of 10

HRVATSKO OTVORENO NATJECANJE IZ INFORMATIKE 2013/2014 1.

KOLO

OPISI ALGORITAMA

HONI 2013/2014 1. kolo, 28. rujna 2013.

Zadatak GLEDATELJ Autor: Marin Tomi

Jednostavan zadatak za zagrijavanje. Potrebno je pronai jednostavnu formulu za broj bodova koju je pojedina ekipa osvojila: 3 * T + 2 * D + S, pri emu je T broj trica, D broj dvica, a S broj slobodnjaka. Potrebno znanje: mnoenje i zbrajanje, uitavanje i ispisivanje Kategorija: matematika, sport

HONI 2013/2014 1. kolo, 28. rujna 2013.

Zadatak PRODAVA Autor: Marin Tomi

Ovaj zadatak moe se rijeiti tako da napiemo 61 uvjet, po jedan za svaki dan prvenstva. Naravno, poeljno je to izbjei koristei elegantniji pristup poput ovog: svakom danu prvenstva dodijelimo redni broj, 1. listopada dobiva broj 1, a 30. studenog dobiva broj 61 sada je dovoljno gledati ostatak rednog broja pri dijeljenju sa 7. Lako je primijetiti da utorak pada na dane s rednim brojem koji daje ostatak 1, srijeda na dane s rednim brojem koji daje ostatak 2, ... Tako moemo zadatak rijeiti sa samo 7 uvjeta, umjesto 61. Dakako, ne smijemo izostaviti dodatna 2 uvjeta za dane kada Mirko prodaje zanimaciju. Potrebno znanje: grananje(if-then), matematika Kategorija: ad-hoc

HONI 2013/2014 1. kolo, 28. rujna 2013.

Zadatak TRENER Autor: Marin Tomi

Potrebno je prebrojati koja slova se u ulazu pojavljuju barem 5 puta kao poetno slovo prezimena. To se moe napraviti tako da se za vrijeme uitavanja u jednom nizu veliine 26 broji koliko puta se koje slovo pojavilo. Nakon uitavanja dovoljno je jednom proi kroz niz i ispisati ona slova koja se pojavljuju barem 5 puta. Takoer treba pripaziti i ispisati PREDAJA u sluaju da nije ispisano nijedno slovo. Za implementacijske detalje pogledajte izvorni kod. Potrebno znanje: nizovi, for-petlja, stringovi Kategorija: ad-hoc

HONI 2013/2014 1. kolo, 28. rujna 2013.

Zadatak KUA Autor: Adrian Satja Kurdija

Optimalnom strategijom rezanja pokazuje se sljedea. Poredajmo kobasice u duinu, jednu za drugom. (Dobivena duina sastoji se od N manjih duina.) Tu duinu prereimo na M jednakih dijelova: to e biti traeno rezanje. Od nainjenih M - 1 rezova nisu svi pravi rezovi: neki se od njih podudaraju s rubovima kobasica (manjih duina), tj. prolaze izmeu kobasica. Primjerice, ako su dvije kobasice a etiri kuaa, prvi rez bit e pravi i rezat e prvu kobasicu na pola, drugi rez nee biti pravi (jer e prolaziti tono izmeu dviju kobasica), a trei rez bit e pravi i rezat e drugu kobasicu na pola. Valja nam dakle prebrojati rubne rezove. Ako je K-ti rez rubni, znai da je prvih K od M dijelova velike duine jednako prvih X kobasica, gdje je X cijeli broj. Drugim rijeima, (K / M) od N kobasica iznosi X kobasica. Drugim rijeima, X = (K * N) / M. Sad je jasno da e X biti cijeli broj (a rez biti rubni) ako je K * N djeljiv s M. Sada for-petljom za svaki mogui K (od 1 do M - 1) na ovaj nain lako provjeravamo radi li se o pravom ili rubnom rezu. Alternativno, mogue je izvesti i eksplicitnu formulu: rjeenje = M nzd(N, M). Dokaz ostavljamo itateljici za vjebu.

Potrebno znanje: for-petlja, mnoenje cijelog broja razlomkom Kategorija: ad hoc

HONI 2013/2014 1. kolo, 28. rujna 2013.

Zadatak RATAR Autor: Matija Buci

Prvi korak ka uspjenom rjeavanju ovog zadatka je pronalaenje naina kako brzo izraunati ukupnu dobit nekog pravokutnika. Dobar nain za to slijedi... Unaprijed emo izraunati (preprocessati) N * N matricu P gdje P[x][y] oznaava sumu vrijednosti u pravokutniku sa nasuprotnim vrhovima (0, 0) te (x, y). Za potrebe ovog zadatka izraunavanje vrijednosti svih takvih pravokutnika dovoljno je izvesti u sloenosti O(N4) prolaenjem kroz cijeli pravokutnik svaki put pri raunanju. Naravno, to je mogue napraviti i u sloenosti O(N2) to ostavljamo itateljici za vjebu. Ovaj postupak je koristan jer sada moemo odrediti ukupnu dobit bilo kojeg pravokutnika u sloenosti O(1) umjesto u sloenosti O(N2) koristei formulu ukljuivanja i iskljuivanja:
suma(x1, y1, x2, y2) = P[x2][y2]+P[x1 - 1][y1 - 1]-P[x1 - 1, y2]-P[x2][y1 - 1]

Jednostavan nain za prebrojati valjane parove pravokutnika je isprobavanje svake etvorke toaka kao mogue nasuprotne vrhove i provjeravanje imaju li zajedniku toku i imaju li istu sumu koristei gornju formulu. Sloenost takvog rjeenja je O(N8) i vrijedi 20% bodova. Gornje rjeenje moemo jednostavno optimizirati tako da ne isprobavamo svaku etvorku toaka kao nasuprotne vrhove, nego fiksiramo zajedniku toku pravokutnicima, ime smo odredili po jedan vrh svakom pravokutniku. Sada nam preostaje fiksirati preostala dva vrha svakom pravokutniku i napraviti potrebne provjere. Tako se sloenost smanjuje na O(N6) i dobiva 40% bodova. Za posljednju optimizaciju potrebno je iskoristiti injenicu da su dobiti jedininih kvadratia brojevi izmeu -1000 i 1000 to znai da je

ukupna dobit svakog pravokutnika izmeu -1000 * N2 i 1000 * N2. Budui da je N najvie 50, moemo napraviti polje veliine 2000 * N2 u kojem brojimo koliko imamo pravokutnika s kojom ukupno dobiti. Recimo da prebrojavamo parove pravokutnika koji se dodiruju u donjoj lijevoj i gornjoj desnoj toki (kao na slici). Fiksiramo zajedniku toku pravokutnika na sve mogue naine. Odabiremo gornji lijevi vrh pravokutnika broj 1 na sve mogue naine i brojimo u polju koliko imamo pravokutnika sa kojom sumom. Nakon toga odabiremo donji desni vrh pravokutnika broj 2 te za svaki pravokutnik odreene sume iz polja oitavamo koliko ima odgovarajuih gornjih lijevih pravokutnika i pribrajamo to u rjeenje. Isto ponavljamo za pravokutnike kojima je zajedniki vrh donja lijeva i gornja desna toka.

Sloenost gornjeg algoritma je O(N4) i on nosi 100% bodova. Za implementacijske detalje pogledajte izvorni kod. Potrebno znanje: koritenje pomonih nizova, baratanje dvodimenzionalnim nizovima (matricama) Kategorija: ad-hoc preprocessing,

HONI 2013/2014 1. kolo, 28. rujna 2013.

Zadatak LOPOV Autor: Domagoj evid

Zadatak se rjeava jednostavnim pohlepnim algoritmom. Sortiramo komade nakita po cijeni. Zatim kreemo od najskupljeg komada prema najjeftinijem i radimo sljedee: ako postoji, uzmi najmanju vreu ija je nosivost vea od teine trenutnog komada nakita. Izbaci tu vreu iz skupa vrea i pridodaj cijenu trenutnog komada u rjeenje ako ne postoji takva vrea, preskoi ovaj komad nakita i nastavi dalje Za implementaciju ovog algoritma potrebna je struktura podataka koja podrava tri operacije: ubaci broj, nai prvi broj vei od nekog broja x ili javi da ne postoji, izbaci neki broj. Oni koji programiraju u C++ mogu iskoristiti gotovu strukturu - multiset. Programeri u Pascalu e se morati malo vie namuiti za ovaj zadatak. Za njih je jednostavnije implementirati sljedei algoritam ija je glavna ideja u osnovi vrlo slina kao i u gore navedenom. Za razliku od gornjeg algoritma gdje je potrebno balansirano binarno stablo ili logaritamska struktura, za ovaj algoritam je potrebno sortiranje i binarni heap to je donekle lake implementirati. Binarni heap je struktura koja podrava tri operacije: ubaci broj, reci koji je najvei broj, izbaci najvei broj. Algoritam je sljedei: sortiraj nakit i vree po teini zajedno u jedan niz kreni od predmeta najmanje teine prema predmetu najvee teine kada naie na komad nakita, ubaci njegovu vrijednost u heap kada naie na vreu, ako heap nije prazan, uzmi najskuplji komad nakita na koji si naiao do sad (on e sigurno imati manju teinu zbog naina na koji smo sortirali) i izbaci ga iz heapa. Njegovu vrijednost pribroji u trenutno rjeenje. Dokaz gornjih algoritama ostavljamo itateljici za vjebu. Potrebno znanje: heap ili multiset, pohlepni algoritmi Kategorija: ad-hoc

HONI 2013/2014 1. kolo, 28. rujna 2013.

Zadatak ORGANIZATOR Autor: Domagoj evid

Primijetimo da je rjeenje veliina tima * broj klubova koji mogu sudjelovati, a sudjelovati mogu svi klubovi kojima je broj lanova djeljiv s veliinom tima. Najjednostavniji nain za prebrojati broj klubova koji mogu sudjelovati za veliinu tima V jest da proemo kroz cijeli niz sa veliinama klubova i brojimo koliko je klubova djeljivo. Sloenost ovog algoritma je O(maxV * N) pri emu je maxV najvea mogua veliina kluba jer veliina tima moe poprimiti sve vrijednosti od 1 do maxV, a za svaku provjeru nam je potrebno N koraka. Potrebno je pronai bolju metodu za raunanje koliko ima ekipa koje se mogu natjecati. Budui da su veliine ekipa brojevi do 2 milijuna, moemo napraviti niz a veliine maxV u kojem e na i-tom mjestu pisati koliko ima ekipa sa i lanova. Da bi izraunali koliko ima ekipa koje mogu sudjelovati ako je veliina tima d, potrebno je izraunati sumu: a[d] + a[2 * d] + a[3 * d] + ..., za to je potrebno maxV / d koraka. Za isprobavanje svih mogunosti od 1 do maxV kao broj d potrebno je: maxV / 1 + maxV / 2 + maxV / 3 + ... + maxv / (maxV-1) + 1 koraka to je otprilike maxV lg maxV. Sloenost ovog algoritma je O(maxV lg maxV) to je dovoljno brzo za osvojiti sve bodove. Potrebno znanje: baratanje s nizovima, izraunavanje sloenosti Kategorija: ad-hoc

HONI 2013/2014 1. kolo, 28. rujna 2013.

Zadatak SLASTIAR Autor: Marin Tomi

Rijeimo prvo jednostavniju verziju zadatka u kojoj robot ne staje nakon to pronae traeni serijski broj nego uvijek isproba svih N segmenata. Neka je f(W, S) broj sufiksa stringa S koji imaju prefiks W. Neka je S[x..y] oznaka za podstring stringa S od mjesta x do mjesta y. Tada je broj usporedbi koje e robot napraviti za rije W duljine L:
BS + f(W[1..1], S) + f(W[1..2], S) + ... + f(W[1..i], S) + ... + f(W[1..L], S),

pri emu je BS ukupan broj segmenata s kojima je robot zapoeo usporedbu. U ovoj pojednostavljenoj verziji zadatka, BS je uvijek N, jer robot ne staje s usporedbama kad pronae rije. Potreban nam je efikasan nain kako izraunati funkciju f(W, S). To moemo napraviti tako da napravimo suffix array stringa S. Suffix array je skup svih sufiksa stringa S sortiranih u leksikografskom poretku. Sada binarnim pretraivanjem moemo u suffix arrayu pronai interval sufiksa koji poinju na slovo W[1]. Neka je taj interval [l1, r1]. Funkcija f(W[1..1], S) je tada r1 - l1 + 1. Zatim unutar tog intervala pronalazimo interval sufiksa kojima je drugo slovo W[2], [l2, r2]. f(W[1..2], S) je r2 - l1 + 1. Postupak dalje postavljamo na isti nain za sva slova stringa W. Sloenost ove pretrage je O(L lg N) to je dovoljno brzo jer suma duljina svih upita nee biti vea od 3 000 000. to kada robot staje kada prvi put naie na rije? Za sve rijei emo izraunati prvo mjesto na kojima se pojavljuju, pi. Neka je g(W, S, p) funkcija koja kae koliko ima sufiksa stringa S sa prefiksom W koji poinju zakljuno sa pozicijom p. Sada moemo izvesti novu formulu za ukupan broj usporedbi: BS + g(W[1..1], S, pi) + ... + g(W[1..L], S, pi), s time da je BS sada pi jer nakon te pozicije stajemo s usporedbama. Kako bi olakali raunanje funkcije g, neemo odgovarati na upite u redoslijedu kojim su nam dani u ulaznim podacima, nego emo ih sortirati na nain koji nama odgovara i odgovore spremiti u jedan niz. Kada izraunamo sve odgovore ispisat emo ih u odgovarajuem poretku.

Upite emo sortirati uzlazno po pi. Takoer emo napraviti strukturu koja podrava dvije operacije: dodaj 1 na neko mjesto, odgovori koja je suma brojeva u nekom intervalu. Ta struktura e nam omoguiti da raunamo koliko ima trenutno bitnih prefiksa u nekom intervalu. Moemo je implementirati pomou logaritamske strukture ili tournament stabla. Upite rjeavamo na sljedei nain: recimo da trenutno odgovaramo na upit koji je pronaen na mjestu pi u strukturi na odgovarajua mjesta za sve sufikse do pi postavljamo jedinice. Valja primijetiti da ne moramo uvijek isponova postavljati jedinice od prvog sufiksa nego samo od sufiksa na kojem smo stali u prolom upitu jer su upiti sortirani po pi. na isti nain kao i u lakoj verziji zadatka pronalazimo intervale [l1, r1], [l2, r2], ..., [lL, rL]. Sada u odgovor ne dodajemo ri - li + 1 ve sumu intervala [li, ri] u strukturi. Ta suma je zapravo odgovor na pitanje koliko ima sufiksa koji poinju do mjesta pi u intervalu [li, ri] u sufix arrayu. izraunati odgovor spremamo u niz sa odgovorima na odgovarajue mjesto Na kraju programa ispiemo niz s odgovorima. Jo je jedna sitnica ostala nerazrijeena, kako pronai brojeve pi? Nakon to za neku rije W pronaemo posljednji interval [lL, rL] znamo da svi sufiksi iz tog intervala imaju prefiks W. Prvo mjesto gdje se pojavljuje je poetno mjesto najlijevijeg od tih sufiksa, tj. sufiks s najmanjim indeksom. Dakle, moramo napraviti strukturu koja e moi odgovoriti koji je najmanji broj u nekom intervalu. To moemo napraviti uz pomo tournament stabla ili slinih struktura. Za implementacijske detalje pogledajte izvorni kod. Postoje razni algoritmi za izgradnju suffix arraya u raznim sloenostima koji se mogu pronai na internetu. U slubenom rjeenju implemetiran je algoritam sloenosti O(N lg2 N). Takoer, u slubenom rjeenju su implementirani tournament i logaritamska struktura. Sloenost svakog upita u tim strukturama je O(lg N). Ukupna sloenost algoritma je O(N lg2 N + suma duljina upita * lg N).

Potrebno znanje: napredne strukture podataka tournament, logaritamska), binarno pretraivanje Kategorija: stringovi, strukture podataka

(suffix

array,

You might also like