You are on page 1of 10

HRVATSKO OTVORENO NATJECANJE IZ

INFORMATIKE

1. KOLO

RJEŠENJA
HONI 2010/11 Zadatak TIMSKO

1. kolo, 23. listopada 2010. Autor: Adrian Satja Kurdija

Primijetimo da možemo formirati tim ako su zadovoljeni sljedeći uvjeti: broj


djevojaka je barem 2, broj mladića je barem 1 i M+N ≥ K+3 (jer tim sadrži troje
ljudi, a još K ih mora otići na praksu). Dakle, nameće se pohlepni algoritam -
formiramo timove dok god to možemo. Preciznije, pseudokodom:

dok je (M ≥ 2 i N ≥ 1 i M+N ≥ K+3) činiti


{
rješenje := rješenje+1; (povećaj broj formiranih timova)
M := M-2; (smanji broj djevojaka)
N := N-1; (smanji broj mladića)
}

Alternativno rješenje:

Ako djevojaka ima barem dvostruko više od mladića, reći ćemo da one čine višak s
obzirom na formiranje timova, a u suprotnom da mladići čine višak. Možemo stoga
K puta učiniti sljedeće: pogledaj čine li djevojke višak, ako čine, smanji broj
djevojaka za 1 (tj. pozovi djevojku na praksu), inače smanji broj mladića za 1 (tj.
pozovi mladića na praksu). Na kraju izračunamo broj timova koji je moguće
formirati od preostalih djevojaka i mladića.

Potrebno znanje:

Usporeñivanje brojeva, while ili for petlja

Kategorija

Ad-hoc, pohlepni algoritmi


HONI 2010/11 Zadatak PROFESOR

1. kolo, 23. listopada 2010. Autor: Goran Gašić

Primijetimo da promatranje svakoga intervala te svake moguće ocjene neće biti


dovoljno brzo za veliku vrijednost N. Ovakvo rješenje složenosti je O( N3 ) te nosi
70% bodova.

Kako bismo ostvarili sve bodove, potrebno je koristiti drugačiji pristup.

Ako pretpostavimo ocjenu koju će profesor dati učenicima, onda možemo u jednom
prolasku kroz sve klupe odrediti najdulji uzastopni podniz klupa takav da u svakoj
klupi možemo pronaći jednoga učenika koji zaslužuje pretpostavljenu ocjenu. Ovo
možemo ostvariti pomoću brojača u kojemu pamtimo trenutačan broj uzastopnih
klupa, čiju vrijednost osvježavamo sa svakom klupom.

Konačno, traženo rješenje jest za svaku ocjenu od jedan do pet provesti opisani
algoritam te uzeti maksimalno pronañeno rješenje.

Primijetimo još da se zadatak može riješiti u složenosti O( N ) i ako su ocjene u


intervalu od 1 do N. Rješenje ovoga problema ostavljamo za vježbu čitatelju.

Potrebno znanje:

for petlja

Kategorija

Ad-hoc, dinamičko programiranje


HONI 2010/11 Zadatak SRETAN

1. kolo, 23. listopada 2010. Autor: Goran Gašić

Naivno rješenje problema jest prolaziti po prirodnim brojevima te odreñivati sretne


dok ne naiñemo na K-ti po redu sretni broj. Ovakvo rješenje nosi 20% bodova.

Navedeno rješenje možemo ubrzati ako primijetimo uzorak u sretnim brojevima.

Naime, ako znamenku 4 zamijenimo nulom, a znamenku 7 zamijenimo jedinicom,


primijetit ćemo da su sretni brojevi bliski prikazu brojeva u binarnom brojevnom
sustavu s time da je ovdje dozvoljena vodeća nula.

Rješenje koje uzastopno generira prvih K sretnih brojeva u skladu s pronañenim


uzorkom složenosti je O( K ) te nosi 50% bodova.

Daljnje ubrzanje donosi promatranje količine sretnih brojeva odreñene duljine.


Sretnih brojeva duljine N ima 2N (jer na svaku od N pozicija možemo postaviti dvije
znamenke).

Znajući ovu činjenicu možemo odrediti duljinu traženoga sretnoga broja te poziciju
meñu sretnim brojevima te duljine. Neka je ta pozicija P. Tada je dovoljno ispisati
broj P-1 u binarnom brojevnom sustavu s odreñenim brojem vodećih nula pritom
zamjenjujući odgovarajuće znamenke četvorkama i sedmicama.

Potrebno znanje:

Prepoznavanje uzoraka, binarni brojevni sustav

Kategorija

Ad-hoc
HONI 2010/11 Zadatak LJUTNJA

1. kolo, 23. listopada 2010. Autor: Adrian Satja Kurdija

Neka je S zbroj svih želja. Zamislimo da smo svakom djetetu dali bombona koliko
želi i da im sad trebamo oduzimati bombone, tako da ih na kraju ostane M. Dakle,
trebamo oduzeti S-M bombona.

Budući da je suma brojeva bombona koji će djeci manjkati konstantna (jednaka S-


M), a želimo da suma kvadrata tih brojeva bude minimalna, treba primijetiti da
ćemo to postići ako ti brojevi budu što “jednakiji”. Naime, matematički se može
pokazati (primjenom nejednakosti kvadratne i aritmetičke sredine) da je suma
kvadrata nekih pozitivnih brojeva, uz fiksnu sumu, najmanja onda kad su oni
jednaki.

Neka je K preostali broj bombona koji trebamo oduzeti (na početku je on jednak S-
M). Naš je cilj da, ako možemo, svakom djetetu oduzmemo jednak broj bombona,
koji iznosi K/N. Ako ne možemo, želimo da broj oduzetih bombona pojedinom
djetetu bude što bliži K/N.

Ako je dijete koje želi najmanje bombona dobilo barem K/N bombona, možemo
ispuniti cilj i oduzeti mu K/N bombona, svodeći tako problem na preostalih N-1
djece (smanjujemo N za 1, računamo novi K i gledamo dijete sa sljedećom
najmanjom željom). Ako je pak dijete koje promatramo dobilo manje od K/N
bombona, pa mu ne možemo oduzeti K/N bombona, oduzet ćemo mu koliko
možemo, tj. sve što ima, te kao i prije rješavamo preostalu djecu.

Na kraju samo ispišemo sumu kvadrata brojeva koje smo oduzimali djeci. Složenost
opisanog algoritma je linearna, ali prije toga moramo uzlazno sortirati želje djece,
pa je ukupna složenost O( N log N ).

Napomenimo da je zadatak moguće riješiti i binarnim pretraživanjem, što


ostavljamo čitateljima za vježbu.

Potrebno znanje:

Sortiranje u O( N log N ), uočavanje matematičkih zakonitosti, pohlepni algoritmi

Kategorija

Pohlepni algoritmi, binarno pretraživanje


HONI 2010/11 Zadatak TABOVI

1. kolo, 23. listopada 2010. Autor: Matija Osrečki, Stjepan Glavina

Ukoliko imamo neko rješenje, možemo odlučiti prvo samo dodavati tabove pa ih
onda samo brisati, budući da poredak operacija nije bitan. To znači da možemo
ignorirati pravilo koje kaže da nikad niti jedan redak ne smije imati manje od nula
tabova.

Zadatak možemo prikazati na ovaj način: zapišimo niz brojeva takav da je i-ti broj
u nizu Ki-Pi. Operacija nam je povećavanje ili smanjivanje svakog broja u nekom
intervalu za jedan (zvat ćemo takve intervale pozitivni i negativni). Potrebno je uz
minimalan broj operacija dobiti niz koji sadrži samo nule.

Rješenje:

Zamislimo neko optimalno rješenje koje se sastoji od niza pozitivnih i negativnih


intervala. Ako postoje, uzmimo jedan pozitivni i jedan negativni interval koji se
prekrivaju.

Promotrimo četiri slučaja:

1. Intervali imaju identične granice, što znači da oba možemo u potpunosti


ignorirati. Ovime dolazimo i do kontradikcije, zato što ovo onda nije
optimalno rješenje.

2. Intervali imaju zajedničku lijevu ili desnu granicu. Možemo ovaj uži
zanemariti, a širi samo skratiti na mjestu gdje se prekriva s užim. Budući da
imamo jednu operaciju manje, i u ovom slučaju dolazimo do kontradikcije.

3. Intervali nemaju zajedničke granice, ali jedan u potpunosti prekriva drugog.


Tada možemo maknuti užeg, a šireg podijeliti na dva dijela, zato što se
mjesta prekrivanja poništavaju (jedan pozitivni i jedan negativni interval na
neki broj istovremeno nemaju nikakvog efekta). Na ovaj način ne mijenjamo
broj korištenih intervala, što znači da je rješenje i dalje optimalno.

4. Intervali nemaju zajedničke granice, ali se djelomično prekrivaju. Možemo


oba intervala samo skratiti na mjestu prekrivanja, čime je rješenje i dalje
valjano, ali i optimalno jer ostaje isti broj korištenih intervala.
Zaključujemo da, kad god možemo u optimalnom rješenju naći jedan pozitivan i
jedan negativan interval koji se prekrivaju, možemo i malo promijeniti rješenje na
opisani način. Svaki put se zbroj duljina intervala smanjuje, što implicira da ćemo u
jednom trenutku sigurno stati. Nakon tog niza transformacija neće postojati niti
jedan pozitivni i niti jedan negativni interval koji se prekrivaju. Time smo dokazali
da uvijek postoji neko optimalno rješenje bez takvih intervala.

Podijelimo niz brojeva na uzastopne dijelove naizmjence na one sa samo


nenegativnim i na one sa samo nepozitivnim brojevima. Te dijelove možemo
pronaći u linearnoj složenosti. Svaki dio možemo zasebno riješiti korištenjem samo
pozitivnih ili samo negativnih intervala. Budući da su oba slučaja analogna, u
nastavku ćemo se fosirati samo na slučaj s nenegativnim brojevima korištenjem
samo negativnih intervala.

Ukoliko postoji nula u nizu brojeva, podijelimo niz na dva dijela, dio lijevo od te
nule i dio desno od te nule te riješimo oba dijela zasebno. To možemo napraviti
zato što nikad nećemo imati interval koji prekriva tu nulu. Ako pak nema nule,
iskoristimo jedan negativni interval za cijeli niz ii ponovimo istu stvar. Na kraju
ćemo ovim postupkom dobiti optimalno rješenje. Dokaz da je to istina nije težak pa
ga prepuštamo čitatelju.

Zamislimo niz brojeva kao histogram, gdje brojevi predstavljaju visine stupaca.
Jedan od načina kojim ćemo naći rješenje za niz brojeva je korištenje rekurzije.
Pronañimo najmanji broj B pomoću tournament stabla. Iskoristimo negativne
intervale na cijelom nizu B puta tako da najmanji broj postane nula. Sad
prepolovimo niz na mjestu gdje je najmanji broj i rekurzivno rješavamo dio lijevo i
dio desno od njega. Složenost ovog algoritma je O( N log N ).

Rekurzivni algoritam zapravo rastavlja histogram na binarno stablo, zato što se u


svakom koraku rekurzije širimo na dva manja slučaja. Umjesto rekurzije, za
rastavljanje histograma na stablo se može koristiti i poznati algoritam složenosti O(
N ) koji koristi stog.

Alternativno rješenje:

Postoji i rješenje koje koristi dinamičko programiranje i ne zahtijeva navedena


dokazivanja pretpostavki. Stanje opisujemo s tri broja:
1. broj otvorenih pozitivnih intervala
2. broj otvorenih negativnih intervala
3. indeks na kojem se trenutno nalazimo

U svakom trenutku možemo:


1. otvoriti novi interval koji počinje na trenutnom indeksu
2. zatvoriti neki prethodno otvoreni interval koji završava na indeksu koji
prethodi trenutnom
3. ako nam odgovara broj otvorenih pozitivnih i negativnih intervala (tako da na
trenutnom indeksu ima zadan broj tabova), pomičemo se na sljedeći indeks

Ovaj algoritam se može implementirati tako da ima složenost O( N*M2 ), gdje je M


najveći broj tabova koji se može pojaviti u retku.

Potrebno znanje:

Pohlepni algorithmi (ispravno korištenje i dokazivanje točnosti), pretvaranje


histograma u binarno stablo korištenjem RMQ struktura ili stacka, dinamičko
programiranje

Kategorija

Pohlepni algoritmi, dinamičko programiranje


HONI 2010/11 Zadatak ŽABE

1. kolo, 23. listopada 2010. Autor: Stjepan Glavina

Primijetimo da žaba broj N-1 skakanjem dolazi na mjesto od kojeg je i počela. Žaba
N pak se ponaša slično kao žaba 1, ona se jednostavno pomakne za jedno mjesto.
Algoritam je ovakav: poredat ćemo žabe s brojevima 1 do N-1 u dobar relativni
poredak (dobar je onaj koji se pojavljuje u konačnom poretku). Na kraju možemo
skakati sa žabom N dok ona ne doñe na pravo mjesto.

Preostaje nam poredati žabe 1 do N-1. Pretpostavimo da smo doveli žabe N-1, N-
2, N-3, ..., X+1 u dobar relativni poredak. Sada želimo i žabu X dovesti u dobar
relativni poredak sa tim žabama. Meñu tim žabama koje smo već poredali
pronañimo onu točno prije koje želimo postaviti žabu X. Onda znamo točan broj
mjesta za koji želimo pomaknuti žabu X. Neka je taj broj D.

Neka je broj G najveći zajednički djelitelj od X i N-1. Pogledajmo kako se kreće


žaba X ako Kralj Žabac uzviče njen broj. Nakon (N-1)/G uzvika ona će se vratiti
na mjesto od kojeg je prvotno počela skakanje. Nakon svakog uzvika vrijednost D
mod G se ne mijenja. Ako nam je D mod G jednako nula, možemo raditi uzvike za
žabu X tako dugo dok nam ona ne doñe na željeno mjesto.

Ukoliko D mod G nije nula, moramo promijeniti taj broj tako da postane nula. Taj
broj možemo postepeno smanjivati na ovaj način: dovedemo žabu broj N točno
ispred žabe X i onda napravimo jedan uzvik za žabu X. Jednom kad nam D mod G
postane nula, možemo ju lako dovesti na pravo mjesto.

Alternativno rješenje:

Zamislimo da imamo funkciju koja nam za neki poredak odredi niz uzvika tako da
se dobije poredak 1, 2, 3, ..., N. Tada možemo iz početnog poretka dobiti upravo
taj pa nam preostaje od njega dobiti konačni. Nañimo niz uzvika za pretvoriti
konačni poredak u 1, 2, 3, ... N. Pomoću tog niza se može napraviti i niz uzvika koji
radi obrnuto. To radimo tako da obrnemo niz uzvika i svaki uzvik zapravo
zamijenimo sa nizom uzvika koji ima takav efekt da žabu X pomiče za X mjesta
prema natrag umjesto prema naprijed - za to je samo potrebno odreñeni puta
napraviti obične uzvike (izračunajte koliko puta).

Još moramo napraviti spomenutu funkciju. Dovest ćemo žabu N-2 odmah iza N-1,
zatim žabu N-3 odmah iza N-2, itd. te na kraju žabu 1 iza 2. Nakon toga je
trivijalno dovesti žabu N iza 1.
Pretpostavimo da želimo žabu X dovesti odmah iza žabe X+1. Dovedimo žabu 1 iza
X+1. Onda žabu 2 iza X+1 ili 1. Onda žabu 3 iza X+1 ili 1 ili 2. Ovo radimo sve do
žabe X.
U ovom trenutku imamo krug koji se sastoji od dva dijela: prvi dio se sastoji samo
od žaba 1 do X, a drugi od X+1 do N-1 (žaba N može biti bilo gdje i nju samo
ignoriramo jer nam ne smeta).
Sada napravimo istu stvar, ali bez žabe X. Dovedemo prvo žabu 1 iza X. Zatim
žabu 2 iza X ili 1, itd. Zadnji korak je dovoñenje žabe X-1 iza X ili 1 ili 2 ili 3 ... ili
X-2. Time smo žabu X doveli odmah iza žabe X+1, što nam je i bio cilj napraviti.

Potrebno znanje:

Teorija brojeva

Kategorija

Ad-hoc

You might also like