Šta je novo?

Srednjoškolski zadaci

Switch

Slavan
Učlanjen(a)
10.03.2008
Poruke
1,467
Poena
350
Imam problem oko nekog bedastog zadatka. Potreban je samo algoritam, radimo u pascalu i do sad nam je najveće dostignuće petlja for. Tako da za eventualno rešenje koje ćete predložiti, ne koristite ništa više od if i for...
Unosi se broj robota i broj dana. Svakog jutra roboti se grupišu u grupe po 3 i po 5, grupe po tri daju 5 novih robota, grupe po pet daju 9 novih. Dele se tako da produktivnost bude maksimalna.Grupe po pet daju 9 novih. Svaki robot funkcioniše tri dana. Koliko će robota biti za n dana?
Ja sam rešio 80 posto zadatka, problem su mi ta tri dana... Znači potreban je samo algoritam, može i neki hint za rešenje ovog problema.
 
Poslednja izmena:
Jel' nemoguce da se unese na pocetku broj robota koji je nemoguce rasturiti na 5x+3y? (tipa 7)
Znaci ako pocetni broj moze da resi jednacinu 5x+3y=br_robota onda:
Kod:
for i := 1 to br_dana do
begin
   x := 0;
   for j := br_robota div 5 downto 0 do
      if x = 0 then
          if j * 5 + (br_robota - j * 5) div 3 = br_robota then
              x := j;
   y := (br_robota - x * 5) div 3;
   Inc(br_robota, x * 9 + y * 5);
End;
Moras jos negde cuvati koliko je robota bilo pre 3 dana pa oduzeti ali to je prosto.
 
Recimo, napravi tri promenjive. Jedna neka ti bude broj robota starih jedan dan, druga dva dana i treca tri dana. Kako prolazi dan za danom svaka od njih dobija vrednost one prethodne, dok se zadnja oduzima od ukupnog broja robota. Kao neka FIFO memorija, ako znas sta je to. A prva promenjiva dobija vrednost broja novoproizvedenih robota prethodnog dana, odnosno posle prve iteracije (nakon prvog dana) broj robota na startu. Oni moraju da rade prvo jedan dan, znaci na samom startu programa sve tri promenjive su 0.

Optimalna raspodela nije neki problem, to si verovatno sam provalio. Verovatno si gimnazijalac, mozda ti zadatak deluje bedast, ali ovakve stvari ce te pratiti jos neko vreme ako nastavis u ovom smeru :).

Edit:
Pretece me alfaunits :)
Edit2:
Moram da se ispravim, sta god da sam rekao za optimialnu raspodelu, pogresio sam, los mi je bio algoritam. Cilj je uposliti sve robote, usled moje nepaznje dobio sam rezultat da je bolje da ti neki idluju... :bottle: . Znaci uposli ih sve, tako da sto vise iskoristis grupe od po 5. Recimo za 54 robota napravis 9 grupa po 5 sljakera i 3 po 3. Fakticki od ukupnog broja robota oduzimas grupe od po tri dok ne dobijes broj koji je bez ostatka deljiv sa 5. Za sintaksu me ne pitaj, lakse cu procitati red kineskog nego red Pascala :d
 
Poslednja izmena:
E takve stvari smo uvek morali da pitamo jer ne pisu ;)
Ako moze ta opcija onda treba matematicki videti da li moze nekad opcija 5x+3y+z gde x nije br_robota div 5 da da vecu produktivnost i tako napraviti petlju ali je ideja ista.
 
Ma da, svakako. Ja sam posao sa pretpostavkom da moze bilo koji broj i onda seljacki delio sa 5, proverio da li moze ostatak sa tri i to, sto svakako nije optimalno :wall:
 
Ok, ljudi hvala vam na odgovorima. Ovako, problem je podeliti te robote na grupe tako da one potom daju maksimalan broj novih robota. Uzima se broj obavezno veći od 7.
Da li je najbolje prvo deliti sa pet, pa ostatak sa tri? Ako je početni broj robota 11, onda ako se prvo podeli sa pet, dobiće se 2 grupe, i jedan neiskorišćen robot. A taj robot bi se mogao iskoristiti ako bi se podelilo u dve gupe po tri i jednu grupu po pet, i na taj način se dobije još i robot više. Tako da ovaj način da se prvo podeli sa pet, pa ostatak sa tri, nije najoptimalniji. E sad na koji način se može postići da se taj početni broj robota podeli u grupe tako da daju najveći broj robota i da ne bude ostatka, odnosno robota koji odmaraju...


Fakticki od ukupnog broja robota oduzimas grupe od po tri dok ne dobijes broj koji je bez ostatka deljiv sa 5. Za sintaksu me ne pitaj, lakse cu procitati red kineskog nego red Pascala
A kako to da postignem? Da oduzimam grupe po tri dok ne dobijem broj bez ostatka deljiv sa 5?
 
Poslednja izmena:
Napravi while petlju, u kojoj od ukupnog broja oduzimaš 3, sve dok ne dobiješ broj deljiv sa 5 to bi izgledalo ovako nekako...

Kod:
i:=0;
while (x mod 5) do
begin
   x:=x-3;
   i:=i+1;
end
x ti je ukupan broj robota, a i ti je brojač koji pokazuje koliko grupa sa po tri robota imaš.

Izvinjavam se ako sam negde omašio sintaksu, davno sam položio programiranje 1.

E sad, ako baš ne može sa while petljom, jer je niste radili, onda može drugi način sa for petljom i malo matematike...

Edit:

Nisam više siguran da li u Paskalu može uslov za while petlju onako kako sam napisao ili mora
while (x mod 5)<>0 do
 
Poslednja izmena:
@Speeder, zbrzao si, ne moze while petlja ;)

@Switch
Da li je najbolje prvo deliti sa pet, pa ostatak sa tri?
Pa stavi na papir i resi matematicki, nemoj sve mi da ti resavamo :D
Znaci uzmes ako je br_robota=5n+1 (daje ostatak 1 pri deljenju sa 5 itd.)
Gledaj to ovako:
Kod:
br_rotoba      opt_grupa
-------------------------
0              0*5+0*3+0*1
1              0*5+0*3+1*1
2              0*5+0*3+2*1
3              0*5+1*3+0*1
4              0*5+1*3+1*1
5              1*5+0*3+0*1 (isprobaj druge opcije)
Pravilo se ponavlja za 6-10.
Sve ostalo se svodi na ove primere. Ako je broj 5n+m (m<4), onda je najbolje imati n grupa od 5 a ostalo kao gore na listi.
Znaci delis sa 5, ostatak sa 3 i mozda ostane koji robot sto ne radi. Ne treba znaci druga for petlja.

Za tvoj primer:
Ako je početni broj robota 11, onda ako se prvo podeli sa pet, dobiće se 2 grupe, i jedan neiskorišćen robot. A taj robot bi se mogao iskoristiti ako bi se podelilo u dve gupe po tri i jednu grupu po pet, i na taj način se dobije još i robot više.
Kako? Dve grupe po pet daju 18 novih
Grupa od pet i dve od 3 daju 9+2*4=17 novih. Znaci dve od pet i jedan sto ne radi daju vishe.
 
Poslednja izmena:
@alfa
Ne može jer nisu radili ili iz nekog drugog (logičkog) razloga?

Mislim da grešiš ti alfa...

Ako doslovno pratiš tekst zadatka:
Svakog jutra roboti se grupišu u grupe po 3 i po 5, grupe po tri daju 5 novih robota, grupe po pet daju 9 novih.
Biće ovako: ako imam 3 robota, oni će napraviti 5 novih, pa će ih ukupno biti 8, a ako imam 5 robota oni će napraviti 9 novih pa će ih ukupno biti 14...

Ako imam 11 robota mogu da ih podelim ovako

5 + 5 + 1 --> 14 + 14 + 1 = 29

ili ovako

5 + 3 + 3 --> 14 + 8 + 8 = 30

A situacija je drugačija ukoliko od 3 robota ujutru bude ukupno 5 robota, a od 5 bude ukupno 9.

U ovakvim situacijama treba jako pažljivo pratiti tekst zadatka... ne bi bilo loše da nam Switch napiše kako doslovno glasi zadatak.

Edit2:
U svakom slučaju, kad razdeliš robote na maksimalan broj grupa od 5 pa od preostalih napraviš maksimalan broj grupa od 3, ostaće ti ili 1 ili 2 robota koji idle-uju.
Onda lepo ispitaš da li je taj ostatak 1 ili 2, pa u zavisnosti od toga rasformiraš 1 ili dve grupe od po 5 i te robote pridružiš u gupe po 3, pa ćeš dobiti maksimalnu produktivnost.
 
Poslednja izmena:
Slazem se speederom. Najoptimalnije je da svi rade. Na koliko god slucajeva isprobali, najbolje je da se svi uposle.
Algoritam:
-Recimo imamo 54 robota, to nije deljivo sa 5 bez ostatka.
-Oduzmemo 3 (jedna grupa od tri robota) to je 51 (nije deljivo sa 5 bez ostatka).
-Oduzmemo 3 (jos jedna grupa) to je 48 (nije deljivo).
-Oduzmemo 3 (jos jedna grupa) to je 45 (deljivo) i tih 45 podelis u grupe od po 5 robota.
Na ovaj nacin si ih sve uposlio i napravice 96 robota.

Da si koristio algoritam da prvo podelis u grupe od po 5, pa ako ima ostatka pokusas da napravis grupe od 3 i batalis ostatak manji od 3 (znaci neko idluje, u ovom slucaju 1 robot), imao bi 95 robota posle jednog dana.

Jeste da je razlika +-1 robot dnevno izmedju ova dva algoritma, ali trazi se najoptimalniji. Dakle, ovo vazi ako tri robota naprave pet pa ih ima 8. To sam zapazio jos tokom pisanja onog prvog posta, gde sam se dva puta editovao.

A sto se tice realizacije, ja sam mislio uz pomoc while, ali je ocigledno niste radili :( . Pokusacu sutra da ti objasnim da simuliras while uz pomoc for, izvini, mnogo mi se spava.
 
Poslednja izmena:
Kad sam video ovaj zadak odlučio sam da ga rešim čisto da malo protegnem vijuge i otkucam neki iole zanimljiv kôd jer od trećeg gimnazije (sad sam brucoš) nisam uradio ovoliko komplikovan algoritam. Evo ga u spojleru pošto je poduži. Napisao sam ga u C-u (jer koristim Mac OS X i Xcode), ali valjda će kolega Switch razumeti sam algoritam (možda bi mogao i da ga prevedem u Pascal). Pitajte ako nešto treba da pojasnim. Ali ima jedan problem, rezultat kalkulacije je uvek neki negativan ogroman broj čak i kad upišem sitne brojeve na početku (znam da se to dešava kad je vrednost veća od limita promenljive), ali ja ne mogu da nađem nigde logičku grešku u algoritmu. Pa postavljam kod jer ste vi sigurno stručniji od mene, pa kažite ako nešto primetite nelogično.

EDIT: Izmenio sam kôd (dodao sam rok trajanja robota od 3 dana)

Kod:
#include <stdio.h>

int osnova (float ulaz) {
	
	int izlaz;
	int brojac = 0;
	while (brojac < ulaz) {
		
		if ( (ulaz-brojac) >= 1 ) { brojac = brojac + 1; }
		else { izlaz = brojac; break;};
	}
	return izlaz;
}

float decimala (float ulaz) {
	
	return ulaz - osnova(ulaz);
}

int main (int argc, const char * argv[]) {
   
	int brojDana;
	int pocetniBrojRobota;
	int brojRobota;
	float kolicnik;
	int jedanDan = 0; // broj robota kojima je ostao jedan dan
	int dvaDana = 0; // broj robota kojima je ostalo dva dana
	int triDana; // broj robota kojima je ostalo tri dana
	
	printf("Unesite broj dana: ");
	scanf("%d",&brojDana);
	printf("Unesite broj robota: ");
	scanf("%d",&triDana);
	
	for (int i = 0; i < brojDana; i++) {
		
		pocetniBrojRobota = jedanDan + dvaDana + triDana;
		
		if ( pocetniBrojRobota < 3 ) { // roboti mogu da se razmnožavaju ako ih ima minimum 3
			
			printf("Nema dovoljno robota za razmnožavanje");
			break;
		}
		else { // ako je broj 3 ili više podeliti sa 5 i testirati da li ih ima manje od 5
			
			kolicnik = pocetniBrojRobota / 5;
			if ( kolicnik < 1 ) { // ako je manje od 1 znači da ih ima manje od 5
				
				brojRobota = pocetniBrojRobota + 5;
			}
			else { // ako je broj robota 5 ili više proveriti da li je broj deljiv sa 5
				
				if ( decimala(kolicnik) == 0 ) { // ako je broj deljiv sa 5 povećati broj robota
				
					brojRobota = pocetniBrojRobota + kolicnik*9;
				}
				else { // ako nije deljiv sa 5 ispitati ostatak
				
					if ( decimala(kolicnik)*5 < 3  ) { // ako je ostatak manji od 3 povećati broj robota
 						
						brojRobota = pocetniBrojRobota + osnova(kolicnik)*9 + 1;
					}
					else { // ako je 3 ili više ispitivati dalje
						
						if ( decimala(kolicnik)*5 == 3) { // ako je ostatak jednak 3 povećati broj
							
							brojRobota = pocetniBrojRobota + osnova(kolicnik)*9 + 5;
						}
						else { // ako je ostatak 4 povećati broj
						
							brojRobota = pocetniBrojRobota + osnova(kolicnik)*9 + 6;
						}
					}
				}
			}
		}
		
		jedanDan = dvaDana;
		dvaDana = triDana;
		triDana = brojRobota - pocetniBrojRobota;
	}
	
	printf("\nBroj robota je: %d",brojRobota);
	
	return 0;
}
 
Poslednja izmena:
@alfa
Ne može jer nisu radili ili iz nekog drugog (logičkog) razloga?
Pishe:
Switch je napisao(la):
Tako da za eventualno rešenje koje ćete predložiti, ne koristite ništa više od if i for..
Verovatno da bi vezbali for.

Mislim da grešiš ti alfa...
Ako doslovno pratiš tekst zadatka:
Biće ovako: ako imam 3 robota, oni će napraviti 5 novih
Da, pogresio sam koliko 3 robota proizvode.

Ovaj test za -3-3-3 mod 5 moze da se izvede sa 4 if-a ili for petljom 0 to 2.
Kod:
a := br_robota - (br_robota div 15) * 15;
for j := 2 downto 0 do
  if (a - j * 5) mod 3 = 0 then
    y := j;
Tako?
 
ima gresku! vidi: http://www.benchmark.rs/forum/showpost.php?p=2093731&postcount=23
evo i mog ultra brute force resenja. :d za koje ne znam ni dal daje tacne rezultate...
c++/cli je jezik, valjda ce biti jasno...
Kod:
int dayone = 0;
int daytwo = 0;
int current = int::Parse(textBox1->Text); //input robota > 7
int numofdays = int::Parse(textBox2->Text); //input dana >= 0
int max = 0;
for(int i=0; i<numofdays; i++) {
[INDENT]max = 0;
current -= dayone; //oduzimaju se "mrtvaci"
//trazi se optimalna podela na grupe, tj. trenutan broj robota = 5*a+3*b+c, a = broj grupa po 5, b = broj grupa po 3, c = ostatak
for (int a=0; a<=current/5;a++){
[INDENT]for (int b=0; b<=current/3;b++){
[INDENT]for (int c=0; c<3;c++){
[INDENT]// ako je validna kombinacija mnozilaca i ako proizvodi trenutno najefikasniji rezultat
if(current == 5*a+3*b+c && current+a*9+b*5 > max) max = current+a*9+b*5;
// ostatak (c) se ne sabira zato sto ne proizvodi nista, tj. sabiraju se samo novi roboti
}
}[/INDENT]
}[/INDENT]
// pomeranje na "stack-u" dana...
dayone = daytwo;
daytwo = current;
current = max;[/INDENT]
}[/INDENT]
textBox3->Text = current.ToString(); // output resenje kada je prosao sve dane

svakako mogu da se optimizuju petlje da ne drljaju bezveze ovoliko, da se sracunaju uslovi unapred i sl. al' ovako je jasnije sta se desava. poenta je da u sustini koristi samo for i if.

ps. 11 robota za 11 dana = 209638 robota i treba mu dobrih 10-ak sec. da sracuna. ULTRA MEGA brute force! :d
pps. bilo bi cool da se saznaju neke sample vrednosti od profesora radi provere algoritma...
 
Poslednja izmena:
Baš je brute force. :)

Grupe od 5 su produktivnije od grupa od 3 i poenta je napraviti što više grupa od 5 i što manje grupa od 3. Uslov da početni broj robota mora biti veći od 7 je ustvari hint jer se svi prirodni brojevi veći od 7 mogu faktorisati pomoću prostih brojeva 3 i 5.

Dakle od početnog broja robota se oduzimaju grupe po 3 dok se ne dobije broj deljiv sa 5 sve ostalo su grupe po 5 robota, ostatak tj. nezaposlenih robota nikada neće biti.

Ako te profesor pita za objašnjenje:
8 -> 1*5 + 1*3
9 -> 0*5 + 3*3
10 -> 2*5 + 0*3
11 -> 1*5 + 2*3
12 -> 0*5 + 4*3
13 -> 2*5 + 1*3
14 -> 1*5 + 3*3
15 -> 3*5 + 0*3
16 -> 2*5 + 2*3
17 -> 1*5 + 4*3
18 -> 3*5 + 1*3
19 -> 2*5 + 3*3

Ako pogledaš broj grupa po tri robota (boldovano), može se uočiti patern 1-3-0-2-4. Dakle broj grupa od tri robota će uvek biti 0 do 4, i to će se ciklično ponavljati počevši od 8.

Tako za bilo koji broj robota možemo da izračunamo index u ovom nizu 1-3-0-2-4 po formuli:
(brojRobota - 8) mod 5

Dakle od broja robota oduzimamo 8 jer nam je to startna pozicija, index nula u onom gore nizu, i onda cepamo dalje po modulu 5 jer imamo 5 članova niza.
Na primer 2166 robota:
(2166 - 8) mod 5 = 2158 mod 5 = 3
Dakle iz niza nam treba član sa indexom 3. :)
10-31-02-23-44 (manji font su indexi niza)
To je u ovom slučaju član koji ima vrednost 2, što znači da će biti 2 grupe od 3 robota.
od početnog broja 2166 oduzimamo tih 6 robota, preostali broj robota tj. 2160 delimo na grupe po 5, dakle imaćemo 432 grupe po 5 robota ili ukupno:
2166 = 2*3 + 432*5

Grupisanje možeš odraditi ovako bez petlji, dovoljno je da napraviš niz koji će da čuva brojeve 1-3-0-2-4 i da po formuli (brojRobota - 8) mod 5 izračunaš index niza, uzmeš broj i to ti je broj grupa po 3 robota. Od ukupnog broja robota oduzmeš broj robota koji idu u grupe po 3 i dobijeni broj podeliš sa 5 kako bi dobio broj grupa po 5 robota.

Što se tiče dana, najlakše je da uradiš iteracijom, tj. for petljom, ovako kako je Bahati uradio, dakle samo skroz spoljna petlja, ove unutra menjaš sa ovim što sam ti napisao gore.

Edit:
Evo ga prepravljen kod koji je napisao Bahati, ovo je Java kod, daje isti rezultat kao i njegov (za 11 i 11), vreme izvršavanja < 1ms. :)
Kod:
        int dayone = 0;
        int daytwo = 0;
        int current = 11; //input robota > 7
        int numofdays = 11; //input dana >= 0
        int max = 0;
        int[] threeMemberGroupsPattern = {1, 3, 0, 2, 4};

        for (int i = 0; i < numofdays; i++) {
            max = 0;
            current -= dayone; //oduzimaju se "mrtvaci"
            int threeMemberGroups = threeMemberGroupsPattern[(current - 8) % 5];
            int fiveMemberGroups = (current - threeMemberGroups * 3) / 5;
            max = current + threeMemberGroups * 5 + fiveMemberGroups * 9;

            // pomeranje na "stack-u" dana...
            dayone = daytwo;
            daytwo = current;
            current = max;
        }
        System.out.println(current); // output resenje kada je prosao sve dane
 
Poslednja izmena:
Jos nam Assembly fali ovde i eto radosti :d . Ne obracajte vreme na duzinu izvrsavanja koda, koliko mi je poznato u srednjoj se na to ne pazi (samo na takmicenjima).
 
Provalio sam gde je program zakazao. Imao sam logičku grešku u okviru funkcije "osnova" koju sam napravio da imitira funkciju "trunc" iz pascala. Sad radi dobro. Evo ga novi kod:

Kod:
#include <stdio.h>

int osnova (float ulaz) {
	
	int izlaz;
	int brojac = 0;
	while (brojac < ulaz) {
		
		if ( (ulaz-brojac) >= 1 ) { brojac++; izlaz = brojac; }
		else { izlaz = brojac; break;};
	}
	return izlaz;
}

float decimala (float ulaz) {
	
	return ulaz - osnova(ulaz);
}

int main (int argc, const char * argv[]) {
   
	int brojDana;
	int pocetniBrojRobota;
	int brojRobota;
	float kolicnik;
	int jedanDan = 0; // broj robota kojima je ostao jedan dan
	int dvaDana = 0; // broj robota kojima je ostalo dva dana
	int triDana; // broj robota kojima je ostalo tri dana
	
	printf("Unesite broj dana: ");
	scanf("%d",&brojDana);
	printf("Unesite broj robota: ");
	scanf("%d",&triDana);
	
	for (int i = 0; i < brojDana; i++) {
		
		pocetniBrojRobota = jedanDan + dvaDana + triDana;
		
		if ( pocetniBrojRobota < 3 ) { // roboti mogu da se razmnožavaju ako ih ima minimum 3
			
			printf("Nema dovoljno robota za razmnožavanje");
			break;
		}
		else { // ako je broj 3 ili više podeliti sa 5 i testirati da li ih ima manje od 5
			
			kolicnik = pocetniBrojRobota / 5;
			if ( kolicnik < 1 ) { // ako je manje od 1 znači da ih ima manje od 5
				
				brojRobota = pocetniBrojRobota + 5;
			}
			else { // ako je broj robota 5 ili više proveriti da li je broj deljiv sa 5
				
				if ( decimala(kolicnik) == 0 ) { // ako je broj deljiv sa 5 povećati broj robota
				
					brojRobota = pocetniBrojRobota + kolicnik*9;
				}
				else { // ako nije deljiv sa 5 ispitati ostatak
				
					if ( decimala(kolicnik)*5 < 3  ) { // ako je ostatak manji od 3 povećati broj robota
 						
						brojRobota = pocetniBrojRobota + osnova(kolicnik)*9 + 1;
					}
					else { // ako je 3 ili više ispitivati dalje
						
						if ( decimala(kolicnik)*5 == 3) { // ako je ostatak jednak 3 povećati broj
							
							brojRobota = pocetniBrojRobota + osnova(kolicnik)*9 + 5;
						}
						else { // ako je ostatak 4 povećati broj
						
							brojRobota = pocetniBrojRobota + osnova(kolicnik)*9 + 6;
						}
					}
				}
			}
		}
		
		jedanDan = dvaDana;
		dvaDana = triDana;
		triDana = brojRobota - pocetniBrojRobota;
	}
	
	printf("\nBroj robota je: %d",brojRobota);
	
	return 0;
}

Meni su nekako ove vaše logike grupisanja malo sumnjive. Aj da objasnim svoju iz kôda koji sam stavio u prethodnom postu.

Izračunao sam koliko se robota po glavi dobija kada se grupišu po tri i po pet. 9 / 5 = 1,8 dok je 5 / 3 = 1,6666... Dakle produktivnije je grupisanje po pet. Stoga algoritam prvo proverava da li je broj robota deljiv sa 5.

Ako jeste ==> brojRobota = pocetniBrojRobota + kolicnik*9;
Ako nije proverava se da li je ostatak.
Ako je ostatak 1 ili 2, to jest manji od 3 ==> brojRobota = pocetniBrojRobota + osnova(kolicnik)*9 + 1;
(ovaj plus 1 se dodaje zato što posle zadnje grupe od 5 robota ima još 1 ili 2 ostatka, a pošto 5 robota proizvode 9, a 6 robota proizvode 10 dodaje se na kraj taj jedan u slučajevima kad ima 1 ili 2 ostatka posle deljenja sa 5)
Ako je ostatak jednak 3 ==> brojRobota = pocetniBrojRobota + kolicnik*9 + 5;
Ako je ostatak 4 ==> brojRobota = pocetniBrojRobota + kolicnik*9 + 6;
(dodaje se 6 jer se krajnjih 9 robota može podeliti kao 5+3+1 ili 3+3+3. 5+3 daje 9+5=14, a 3+3+3 daje 5+5+5=15 što je za 6 više od broja koji se dobija kada bi se zanemarila 4 robota ostatka.)

BTW, jel može neko da mi kaže kako da namestim da se code box skroluje, da ne moram da stavljam ovako u spojler.
 
Poslednja izmena:
Pošto ne znam sintaksu C++, nisam mogao u potpunosti ispratiti kod. Što se tiče podele robota na grupe, mislim da sledeće rešenje funksioniše, g3 su grupe po tri robota, a r je broj robota.

Sad je problem samo to što roboti funkcionišu samo tri dana... Ne znam kako bi se to moglo rešiti.
Bacite pogled na ovaj algoritam, pa recite da li je ok?
 
Poslednja izmena:
@ivan90BG
Tebi je ovde nesto dibidus netacno. Na stranu sto te uospte nisam razumeo, ali ti ces recimo posle jednog dana sa 14 robota na startu da imas svega 32 robota (postojeci+novi). Znaci da su 14 robota za jedan dan napravili samo jos 18 tj. radile su dve grupe od po 5 i napravile tih 18. Mogao si da formiras jos jednu grupu od 3 robota, koji bi dali jos 5 to je 37 ukupno. Ali cak ni to nije maksimum. Po mom algoritmu imao bi 38 robota posle jednog dana.

Nije mi bas najjasnije sta si radio...
 
@Switch, mislim da ti je algoritam tacan.
A to kako da pratis robote, pa lako:
r0, r1, r2, rn: Integer;
r0 := 0; r1 := 0; r2 := 0;
rn := 0;

for i := 1 to br_dana Do
Begin
// loop koji trazi kako da se napravi najvise novih robota ide ovde
if (i mod 3) = 0 then
begin
br_robota := br_robota + novi_roboti - r0;
r0 := br_robota;
end;
if (i mod 3) = 0 then
begin
br_robota := br_robota + novi_roboti - r1;
r1 := br_robota;
end;
if (i mod 3) = 0 then
br_robota := br_robota + novi_roboti - r2;
r2 := br_robota;
end;
End;

Nisam siguran da li je bash ovako, posto sam jako pospan, mozda treba da neka var. ide u temp pa se tek onda oduzimaju, ali ne mogu da razmisljam sada ;)
 
Evo ti kompletan zadatak, za koji iskreno verujem da je tacan. Problem je sto je u C-u (ali sam se trudio da sto detaljnije komentarisem) i sto sam koristio while...

Nema smisla stavljati pod spoiler, usled mnogo komentara sve se izmesa. Evo ti u txt fajlu, samo iskljuci word wrap :)
 

Prilozi

  • source.txt
    2.3 KB · Pregleda: 45
Poslednja izmena:
Em je u c-u em ima while petlju ;)

Evo ispravan kod u Pascalu, proverio sam ga:

Kod:
Program Roboti;
Var R, d, d0, d1, d2, i, j, brrob, ost, x, y, z, x1, y1, novi, novi1: Integer;
Begin
     Writeln;
     Write('Unesi broj robota: ');
     Readln(R);
     Write('Unesi broj dana: ');
     Readln(d);
     d0:=R;	{roboti stari 0 dana}
     d1:=0;	{roboti stari 1 dan}
     d2:=0;	{roboti stari 2 dana}
     For i:=1 to d do	{petlja koja broji dane}
     Begin
          brrob:=d0+d1+d2;	{ukupan broj robota koji pocinju proizvodnju tog dana}
          x:=brrob div 5;	{ovde pocinje odredjivanje najobicnije raspodele}
          ost:=brrob mod 5;
          y:=ost div 3;
          z:=ost mod 3;
          novi:=x*14+y*8+z;	{broj robota u slucaju najobicnije raspodele}
          For j:=1 to 2 do	{a odavde se na osnovu ostatka od te raspodele odredjuje najbolja}
          Begin
               If ((z=j) and (x>=j)) then	{posto ostatak tj. z, ako ga ima, moze biti samo 1 ili 2 ispituje se koliki je}
               Begin				{i na osnovu toga se odredjuje broj grupa od po 5 robota koje ce se rasformirati}
                    x1:=x-j;			{a roboti iz rasformiranih grupa pridruziti grupama od po 3 robota}
                    y1:=y+2*j;
               End;
               novi1:=x1*14+y1*8;	{ovde se racuna broj robota nakon nadjene najbolje raspodele}
	       if novi1>novi then novi:=novi1;	{poredi se da li je nova raspodela bolja od prethodne, i uzima se najbolja}
          End;
          d2:=d1;		{sada se roboti "stare" za jedan dan, a oni stari 3 dana se automatski odbacuju}
          d1:=d0;
          d0:=novi-brrob;	{ovo su potpuno novi roboti}
     End;
     Writeln('Konacni broj robota je: ',d0+d1+d2);
     Readln;
End.
 
Poslednja izmena:
zeznuo sam mini stack u prethodnom. sada cuva samo proizvedene tog dana, a ukupan broj se racuna sabiranjem svih "starosnih grupa" na pocetku svakog dana.
to mu dodje 11@11=670292

Kod:
int daythree = 0;
int daytwo = 0;
int dayone = int::Parse(textBox1->Text); //input robota
int numofdays = int::Parse(textBox2->Text); //input dana
int max = 0;
int current,dayend,amax,bmax;
for(int i=0; i<numofdays; i++) {//prodji kroz sve dane
	max = 0;
	current = dayone+daytwo+daythree;
	amax=current/5; //maximalan broj grupa od 5 (petica), ne moze ih biti vise od petine ukupnog broja
	bmax=current/3; //maximalan broj grupa od 3 (trojki), ne moze ih biti vise od trecine ukupnog broja
	for (int a=0; a<=amax;a++){
		for (int b=0; b<=bmax;b++){
			for (int c=0; c<3;c++){ //ostatak mora biti manji od 3 ili bi bio smesten u grupu od tri
				if(current == 5*a+3*b+c && a*9+b*5 > max) max = a*9+b*5;
			}
		}
	}
//sada se u stacku cuvaju samo proizvedeni roboti, oni stariji od tri dana ispadaju
	dayend = current+max;
	daythree = daytwo;
	daytwo = dayone;
	dayone = max;
}
textBox3->Text = dayend.ToString(); //output

ako neko ima predlog kako efikasnije pronaci optimalnu raspodelu, bez nizova, modula, while-ove i sl. neka kaze. :)

iliti:
X = 5*A+3*B+C
Y = 9*A+5*B
gde je X trenutni broj robota, Y broj proizvedenih robota, A broj grupa po 5, B broj grupa po tri i C broj slobodnih robota
pri cemu je X>7 i jedino poznato; A,B,C,Y su nenegativni celi brojevi

naci (dokazati!) A i B takvo da Y bude najvece moguce.

mislim da je zbog ovakvih stvari izmisljena informatika, kao odvojena nauka od matematike. sve je to lepo sto vama intuicija kaze da valja da ima sto vise grupa po 5 i sto manje slobodnih, matematicki gledano ovo je gadan problem. meni bar. :)

ps. prilicno sam siguran da je ovo ono sto se trazi, barem sto se forme tice, tj. ako nisam zeznuo jos nesto, pa ako ima neko da mu prebaci u pascal...

pps. UPS! poslednjeg dana ne sme da izgubi "matorce" pre vremena, tj. i oni ucestvuju u ukupnom zbiru. prema algoritmu i rucno meni izadje 8@4 = 448
 
Poslednja izmena:
Em je u c-u em ima while petlju ;)

Evo ispravan kod u Pascalu, proverio sam ga:

krastavac. ne znam Pascal, :( . U svakom slucaju i ja mislim da je tvoje resenje to sto mu treba, ali zasto mnozis sa 14 i 8? Valjda 9 i 5?
 
Poslednja izmena:
@WebWolf

Otkrio sam još jednu grešku koju ne znam kako da ispravim.

Kod:
float decimala (float ulaz) {
	
	return ulaz - osnova(ulaz);
}

Ovo je definicija funkcije "decimala" koja funkcioniše kao "frac" u pascalu. Funkciju "osnova" sam definisao ranije i ona provereno radi (kao "trunc" u pascalu). E sad, ova funkcija "decimala" uvek izbacuje nulu. U čemu je stvar?

(trunc u pascalu odstranjuje decimalu od celog broja i izbacuje ceo deo, frac odstranjuje ceo deo, a izbacuje samo decimalni deo)
 
Poslednja izmena:
krastavac. ne znam Pascal, :( . U svakom slucaju i ja mislim da je tvoje resenje to sto mu treba, ali zasto mnozis sa 14 i 8? Valjda 9 i 5?

Pisao sam o tome već. Zadatak kaže
grupe po tri daju 5 novih robota, grupe po pet daju 9 novih
Znači, ako imaš grupu od 3 robota, oni će napraviti 5 novih, pa će ih ukupno biti 5+3=8, a ako imaš grupu od 5 robota, oni će napraviti 9 novih, pa će ih ukupno biti 9+5=14.
;)

E da, problem sa mojim kodom je u tome što neće hteti da ti izbaci broj koji je veći od 32767... verujem da se može namestiti nešto što bi u c-u odgovaralo long int, ali ne sećam se više kako.
 
@ivan90BG
Predlazem ti da skratis sebi muke. Secas se cast operatora? :)

Kada float castujes u int, on ce dati samo njegovu celobrojnu vrednost. Nemas potrebe za ovom funkcijom osnova. Pokusaj tako. Ako nista vise, postace malo preglednije.

Edit:
@Speeder
Aham, dobro :). Ne pazim na casu :).
 
Poslednja izmena:
Al ja nemam problem sa funkcijom "osnova". Ona radi odlično (jes' da jede dosta klok ciklusa za velike brojeve, al radi). Moj algoritam zavisi od funkcije koja izbacuje decimalni deo, jer pomoću njega proveravam ostatak množeći ga sa 5 (trenutno ne znam drugačije u C-u). Ako je sintaksa funkcije "decimala" tačna, trebao bi da izađe decimalni deo (funkcija izbacuje razliku između ulaznog broja i celog dela koji izbacuje funkcija "osnova"), ali uvek izlazi samo nula i zato se onda dobija pogrešan rezultat razmnožavanja robota jer putanja grananja uvek odlazi u istom pravcu.

Zato pitam ima li nešto pogrešno u funkciji "decimala", a i da li postoji neki drugi način da u C-u dobijem ostatak deljenja ili decimalni deo broja.
 
mislim da je zbog ovakvih stvari izmisljena informatika, kao odvojena nauka od matematike. sve je to lepo sto vama intuicija kaze da valja da ima sto vise grupa po 5 i sto manje slobodnih, matematicki gledano ovo je gadan problem. meni bar. :)

Upravo tako. :) Sva rešenja ponuđena u ovom thread-u su bazirana na zdravoj logici i to može tako da prođe da Switch odnese zadatak profesoru, ali ono što nama deluje da je dobro, ne mora da znači da je sigurno dobro. Prosto fali nam matematički dokaz optimalne raspodele, meni je to u suštini i najizazovniji deo ovog zadatka, ostalo je fizički posao.

Postavljao sam zadatak na pet različitih načina, sa pet različitih pristupa :D i vrtim se u krug, trenutno sam se zapetljao sa nekim izvodima i čini mi se da odustajem za danas. :)
 
Pa kod koji sam ja dao upravo sam traži najbolju raspodelu za svaki broj robota. Valjda se slažemo da je potrebno imati što više grupa po pet robota. E sad, pitanje je samo da li je bolje imati jednu ili dve takve grupe više, ali da nam zato jedan ili dva robota ne rade (slučaj 1), ili je bolje imati jednu ili dve grupe od pet robota manje, ali da oni preostali budu svi angažovani u grupama od po tri (slučaj 2).
Program koji sam napisao najpre izračunava koliko bi se robota dobilo ako se primeni raspodela iz slučaja 1, a potom isto izračuna ako se primeni raspodela iz slučaja 2. Nakon toga rezultati ta dva slučaja se upoređuju i kao tačan se uzima veći.

Edit:
Sad videh ovo:
pps. UPS! poslednjeg dana ne sme da izgubi "matorce" pre vremena, tj. i oni ucestvuju u ukupnom zbiru. prema algoritmu i rucno meni izadje 8@4 = 448

Meni nekako bilo logično da se roboti raspadnu čim naprave treću turu pa da se ti matori ne računaju u konačnom zbiru, ali mislim da je Bahati u pravu... onda je odgovarajući kod sledeći:

Kod:
Program Roboti;
Var R, d, d0, d1, d2, d3, i, j, brrob, ost, x, y, z, x1, y1, novi, novi1: Integer;
Begin
     Write('Unesi broj robota: ');
     Readln(R);
     Write('Unesi broj dana: ');
     Readln(d);
     d0:=R;	{roboti stari 0 dana}
     d1:=0;	{roboti stari 1 dan}
     d2:=0;	{roboti stari 2 dana}
     d3:=0;
     For i:=1 to d do	{petlja koja broji dane}
     Begin
          brrob:=d0+d1+d2;	{ukupan broj robota koji pocinju proizvodnju tog dana}
          x:=brrob div 5;	{ovde pocinje odredjivanje najobicnije raspodele}
          ost:=brrob mod 5;
          y:=ost div 3;
          z:=ost mod 3;
          novi:=x*14+y*8+z;	{broj robota u slucaju najobicnije raspodele}
          For j:=1 to 2 do	{a odavde se na osnovu ostatka od te raspodele odredjuje najbolja}
          Begin
               If ((z=j) and (x>=j)) then	{posto ostatak tj. z, ako ga ima, moze biti samo 1 ili 2 ispituje se koliki je}
               Begin				{i na osnovu toga se odredjuje broj grupa od po 5 robota koje ce se rasformirati}
                    x1:=x-j;			{a roboti iz rasformiranih grupa pridruziti grupama od po 3 robota}
                    y1:=y+2*j;
               End;
               novi1:=x1*14+y1*8;	{ovde se racuna broj robota nakon nadjene najbolje raspodele}
	       if novi1>novi then novi:=novi1;	{poredi se da li je nova raspodela bolja od prethodne, i uzima se najbolja}
          End;
	  d3:=d2;
          d2:=d1;		{sada se roboti "stare" za jedan dan, a oni stari 3 dana se automatski odbacuju}
          d1:=d0;
          d0:=novi-brrob;	{ovo su potpuno novi roboti}
     End;
     Writeln('Konacni broj robota je: ',d0+d1+d2+d3);
     Readln;
End.
 
Poslednja izmena:
Nazad
Vrh Dno