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

Zadatak VLAK Autor: Adrian Satja Kurdija

Pogledamo li raspored mjesta, lako vidimo da zadatak možemo riješiti s pomoću


nekoliko if-ova: ako je A jednak 1 ili 2, ispiši 8; ako je A jednak 3 ili 4, ispiši 5; ako
je A jednak 5 ili 6, ispiši 4; ako je A jednak 7 ili 8, ispiši 1.

Pozivamo čitatelje da razmotre i alternativno rješenje čiji se priloženi kod vlak.py


sastoji od samo jedne linije.

potrebno znanje: if-then-else


kategorija: ad-hoc

Zadatak NEPAR Autor: Marin Tomić

Pretpostavimo da možemo staviti brojeve u crvenu i plavu kutiju tako da je uvjet


zadovoljen. Budući da je zbroj brojeva u crvenoj kutiji paran, a u plavoj neparan,
slijedi da zbroj svih brojeva mora biti neparan.

Zaključujemo da moramo ispisati “NE” ako je zbroj naša četiri broja paran.

Dalje, označimo brojeve iz ulaza sa A, B, C i D. Ako im je zbroj neparan, to znači


da su zbrojevi A+B i C+D različite parnosti. Ako je zbroj A+B paran stavljamo
brojeve A i B u crvenu, a C i D u plavu kutiju. Inače stavljamo C i D u crvenu, a A i B
u plavu kutiju.

potrebno znanje: if-then-else, matematika


kategorija: matematika
Zadatak PROSJEK Autor: Goran Gašić

Neka je Sk zbroj prvih k brojeva u nizu A. Vrijedi

Sk
Bk = k
Slijedi

Sk+Ak+1
Bk+1 = k+1
Odavde dobivamo izraz za Ak+1

Ak+1 = (k + 1) ∙ Bk+1 − Sk

Elemente niza Ak+1 te njihov zbroj Sk iterativno računamo jednom petljom po nizu
B.

potrebno znanje: operatori, nizovi


kategorija: ad-hoc

Zadatak KLOPKA Autor: Adrian Satja Kurdija

Jednim prolaskom po danim točkama (ili tijekom njihovog unošenja) pronalazimo


najljeviju točku (onu s najmanjom x koordinatom), najdesniju točku (onu s
najvećom x koordinatom), najnižu točku (onu s najmanjom y koordinatom) i
najvišu točku (onu s najvećom y koordinatom). To činimo standardnim algoritmom
nalaženja minimuma/maksimuma: pamtimo dosadašnji minimum/maksimum,
uspoređujemo ga s novom vrijednosti i po potrebi mijenjamo.

Pronađena četiri ruba određuju pravokutnik, ali nama treba kvadrat. Da bi kvadrat
prekrio sve točke, njegova stranica mora biti jednaka većoj stranici spomenutog
pravokutnika. Kad smo pronašli duljinu stranice kvadrata, njezinim kvadriranjem
(množenjem sa samom sobom) dobivamo traženu površinu.

potrebno znanje: for-petlja, nalaženje minimuma i maksimuma


kategorija: ad-hoc
Zadatak PIRAMIDA Autor: Marin Tomić

Prvo, uočimo da obrtanje smjera riječi iz reda u red ne igra nikakvu ulogu što se
tiče broja pojedinih slova u nekom retku.

Naivno rješenje bilo bi simulirati upisivanje slova u svaki redak te brojati broj
pojavljivanja pojedinog slova u svakom retku u matricu broj[26][N]te samo
ispisati vrijednost u matrici za svaki upit. Memorijska složenost ovog rješenja je
O(N), a vremenska O(N2+K), što je dovoljno za 50% bodova. Implementaciju
ovog rješenja možete naći pod imenom piramida_n2.cpp.

Za efikasnije rješenje potrebno je proučiti kako izgleda string snapisan u


pojedinom retku. Naime, postoje dvije mogućnosti:

1) s = w[i..j]za neke ii j. Drukčije rečeno, string sje podstring stringa w.


2) s = w[i..L] + x * w + w[0..j]za neke ii j. Odnosno, string sse
sastoji od nekog sufiksa stringa s(moguće i praznog), zatim cijele riječi w
ponovljene xputa i, konačno, nekog sufiksa stringa w(moguće i praznog)

Npr. kada bi riječ wbila “ABCD”, 12. red piramide bio bi:
CDABCDABCDAB = CDA + 2 * ABCD + AB = w[1..4] + 2 * w + w[0..2] 

Da bismo mogli odrediti x, ii jza neki redak, moramo moći odrediti kojim slovo
riječ započinje u tom retku. Lako se pokaže da je za redak rto ta pozicija jednaka
ostatku dijeljenja broja r * (r­1) / 2s m. Potrebno je pažljivo implementirati ovu
formulu jer rmože biti vrlo velik. Kada smo odredili poziciju, lako je odrediti
parametre x, ii j.

Sada možemo izvesti formule za pojedine slučajeve. Neka f(c, i, j)označava


broj pojavljivanja c-tog slova abecede u podstringu w[i..j]. Formule su sljedeće:
1) broj_pojavljivanja = f(c, i, j)
2) broj_pojavljivanja = f(c, i, L) + x * f(c, 0, L) + f(c, 0, j)

Da bismo efikasno implementirali ovo rješenje, potrebno je moći brzo izračunati


vrijednosti funkcije f. To možemo napraviti tako da izgradimo matricu p[26][L]
kojoj na mjestu [i][j]piše koliko se puta i-to slovo abecede pojavljuje u
podstringu w[0..j]. Tada f(c, i, j)računamo po formuli f(c, i, j) = 
p[c][j] ­ p[c][i­1].

Memorijska složenost ovog rješenja je O(M), a vremenska O(M+K), što je bilo


dovoljno za sve bodove na HONI-ju. Ovo rješenje implementirano je u datoteci
piramida_honi.cpp.
Na COCI natjecanju ovo rješenje je nosilo 70% bodova jer je maksimalna duljina
stringa bila veća pa matrica dimenzija 26 * Lnije stala u 32 MB. Potrebno je bilo
rješavati upite odvojeno za svako slovo. Tako bi umjesto polja dimenzije 26 * L
bilo dovoljno polje dimenzije L. Ovo rješenje implementirano je u datoteci
piramida_coci.cpp.

potrebno znanje: preprocesiranje, matematika


kategorija: ad-hoc, preprocesiranje

Zadatak MAFIJA Autor: Adrian Satja Kurdija

U ovom zadatku funkcionira pohlepni algoritam: ako postoji osoba X koju nitko nije
optužio, nju možemo proglasiti mafijom. Ako je ta osoba optužila osobu Y, onda
osobu Y ne možemo proglasiti mafijom pa i nju možemo potpuno ukloniti. Prilikom
uklanjanja osobe Y, osobi Z koju je ona optužila valja smanjiti brojač koliko je puta
optužena, tako da može eventualno biti proglašena mafijom.

Nakon ponavljanja ovoga postupka dok god možemo, ostat će nam ciklusi, tj. više
neće biti osobe koju nitko nije optužio. Tada bilo koju osobu možemo proglasiti
civilom i ukloniti, pa ćemo moći opet primijeniti gornji postupak, i tako dalje, sve
dok uopće ima neoznačenih osoba.

Čitatelji koji znaju mnogo o grafovima primjetit će da zadatak zapravo traži


maksimalni independent set na pseudošumi (pseudoforest). Isplati se odabirati
listove, brisati njihove susjede i ponavljati postupak sve dok ne ostanu (lako
rješivi) ciklusi. Ovo je rješenje potpuno ekvivalentno prethodnome, ali ga je lakše
vizualizirati.

Oba slučaja potrebno je pažljivo implementirati da složenost algoritma bude O(N).

potrebno znanje: grafovi ili pohlepni algoritmi


kategorija: ad-hoc

Zadatak ZABAVA Autor: Adrian Satja Kurdija

Najprije treba primijetiti da redoslijed useljavanja studenata u zgrade nije bitan: sve
što je bitno jest koliko će studenata useliti u koju zgradu, jer zabave se u pojedinoj
zgradi događaju potpuno neovisno o drugim zgradama. Možemo dakle
pretpostaviti da nam je zadano M brojeva: koliko studenata useljava u koju
zgradu.

Promatrajmo neku zgradu, pretpostavimo da ćemo je isprazniti točno P puta i


pogledajmo kako je treba optimalno prazniti. Pretpostavimo da smo je prvi put
ispraznili nakon što je u nju ušlo x(1) studenata, drugi put nakon što je u nju ušlo
novih x(2) studenata, i tako dalje do posljednjeg pražnjenja nakon x(P) studenata,
nakon čega je do kraja u zgradu ušlo još x(P + 1) studenata.

Buka prije prvog pražnjenja tada iznosi 1 + 2 + … + x1 = x1(x1 + 1)/2, a


analogna formula vrijedi i za buke nakon prvog, drugog i daljnjih pražnjenja.
Ukupna buka u zgradi stoga iznosi

½ * suma( xi(xi + 1) ), za i = 1 … P + 1.

Zanemarimo li dijeljenje s dva, ova buka jednaka je sumi kvadrata xi^2 uvećanoj
za običnu sumu xi, ali potonja je konstantna i jednaka ukupnom broju studenata
koji su doselili u dotičnu zgradu. Treba dakle minimizirati sumu kvadrata P + 1
brojeva čija suma je zadana.

Iz nejednakosti aritmetičke i kvadratne sredine slijedi da je suma kvadrata


najmanja kad su brojevi međusobno jednaki. Nama je to ponekad nemoguće
ostvariti zbog (ne)djeljivosti, ali zato će biti “skoro jednaki”, tj. međusobno će se
razlikovati za 0 ili 1. Ovo dijeljenje i traženu sumu lako je izračunati u konstantnom
vremenu s pomoću jednostavnih formula. Time smo efikasno riješili problem za
jednu zgradu i fiksirani broj pražnjenja te zgrade.

Zadatak sada možemo riješiti dinamičkim programiranjem. Ako dp(m, k) označava


najmanju buku koju možemo postići u prvih m zgrada uz ukupno k pražnjenja, tu
vrijednost računamo tako da na sve moguće načine odaberemo broj pražnjenja
m-te zgrade (nazovimo ga P) i provjerimo je li dobivena buka, koja iznosi

dp(m - 1, k - P) + (rješenje za m-tu zgradu s P pražnjenja, opisano gore),

dosad najmanja. Konačno rješenje, naravno, iznosi dp(M, K). Složenost je


algoritma O(MK2).

potrebno znanje: matematička analiza problema, dinamičko programiranje


kategorija: dinamika
Zadatak KAMP Autor: Antonio Jurić

Promotrimo slučaj kada je kamp postavljen kod kuće broj 1. Budući da je selo
predstavljeno kao graf stabla, put od kampa do bilo koje pojedinačne kuće u koju
idu volonteri je jedinstven. Pretpostavimo da se Mirko nakon što odveze sve
ekipe mora vratiti u kamp.

Kada doveze jednu ekipu do njihove kuće i ako se do kuće u koju ide neka druga
ekipa ide preko ove trenutne kuće, onda će naravno odmah odvesti i njih zbog
uštede vremena. Zbog pretpostavke da se Mirko na kraju mora vratiti u kamp,
rješenje bi tada bila dvostruka suma svih bridova koji povezuju kamp i sve kuće
u koju idu volonteri.

No, budući da je uvjet zadatka da Mirko ostaje pomagati zadnjoj ekipi (ne vraća se
u kamp), najbolje je uvijek na kraju odvesti najudaljeniju ekipu jer tako smo
bridove u grani stabla koja vodi do najudaljnije kuće prošli samo jednom pa je
konačno rješenje: dvostruka suma svih bridova koji povezuju kamp i sve kuće u
koju idu volonteri umanjena za duljinu bridova u najdužoj grani.

Pronalazak bridova koji povezuju kamp i kuće u koje idu volonteri može se
napraviti u složenosti O(N), a kada taj algoritam primijenimo tako da isprobamo
postaviti kamp u svaku kuću, konačna složenost je O(N2) i to rješenje donosi pola
bodova.

Označimo s K minimalno podstablo zadanog stabla koji sadrži sve kuće u koje
moraju doći volonteri i možda još neke kuće koje su na putu između kuća
volontera. Označimo sa S sumu svih bridova podstabla K. Tada rješenje za neku
kuću X glasi:

rjesenje[X] = udaljenost[X] + 2*S – najdalji[Y],

gdje je udaljenost[X] najmanja udaljenost kuće X do skupa K, konkretno do neke


kuće Y iz skupa K, a najdalji[Y] je duljina najdužeg lanca iz kuće Y u skupu K. Ova
formula pretpostavlja da je poznata duljina najdužeg lanca za svaku kuću u K što
je moguće izračunati pažljivim DFS obilaskom po stablu. Složenost ovog rješenja
iznosi O(N) i ono donosi sve bodove. Za detalje oko računanja najdužeg lanca iz
svake kuće u K pogledati priložene kodove.

potrebno znanje: stablo, DFS


kategorija: teorija grafova

You might also like