Cuprins

Tema 3: Comoara faraonului

Obiective

Informații

Descriere

Un faraon foarte bogat voia să-şi ascundă comorile, aşa că a cerut să i se construiască un seif în forma unei piramide. El a mai cerut ca acesta să aibă o singură intrare (prin vârful piramidei), adică să se poată intra numai urcând pe trepte, şi anumite secvenţe de paşi să blocheze calea de acces (din vârf).

Peste ceva timp, după ce piramida este gata, faraonul vrea să-şi verifice comorile, dar nu-şi mai aminteste pe care trepte trebuie să calce. Faraonul e bătrân şi s-a gândit că va avea problema aceasta, aşa că a cerut următoarele pentru a-i fi mai uşor să găsească drumul:

Harta:

Indicaţii

Cerințe

  1. Aflaţi costul drumului valid ales după optimul local (la fiecare pas unde are de ales dintre stânga şi sus, alege treapta cu costul mai mic; preferă SUS când costurile sunt egale);
  2. Aflaţi costul drumului valid ales după optimul global (drumul cu cea mai mică sumă dintre cele posibile);
  3. Simulaţi un număr de drumuri valide ca încercări pentru a găsi un drum sigur (vă opriţi la primul drum sigur găsit), unde fiecare pas este ales “la întâmplare”(excepţie atunci când există o singură variantă pentru următorul pas - când am ajuns deja pe prima linie sau pe prima coloană)
  4. (bonus) Aflaţi numărul de drumuri valide sigure.
pentru a alege “la întâmplare” paşii, toţi studenţii vor folosi aceeaşi funcţie pseudo-aleatoare(rand) cu aceeaşi valoare iniţială(seed), iar fiecare simulare va respecta următoarea schemă:
//cât timp linia (i) != prima linie şi coloana (j) != prima coloană
	dacă (rand() % 2) Mergi in SUS (linia i-1, coloana j);
	altfel Mergi in STANGA (linia i, coloana j-1);
//pentru restul de paşi (după ce i == prima linie sau j == prima coloană),
	există un singur sens posibil
	//MODULATOR = 2^31 - 1
	#define MODULATOR 2147483647
	#define MULTIP 1103515245
	#define INCREMENT 12345
	unsigned int seed = 0;
	int rand() {
		seed = (MULTIP * seed + INCREMENT) % MODULATOR;
		return seed;
	}

Intrare(Harta):

  1. C1, C2, C3, C4 = 4 indicatori(vor avea valoarea 1 sau 0 fiecare);
  2. n = înălţimea piramidei;
  3. S = suma maximă admisă (pentru ca un drum să fie sigur);
  4. valorile din matricea(n x n) ce reprezintă piramida;
  5. nrMaxIncercări = limita pentru a treia cerinţă;

Iesire(fiecare pe un alt rand):

  1. Dacă (C1 == 1): S1 = suma de la prima cerinţă(drumul obţinut alegând mereu optimul local)
  2. Dacă (C2 == 1): S2 = suma de la a doua cerinţă(drumul obţinut căutând optimul global)
  3. Dacă (C3 == 1): nrIncercari sau 0; 0 la ieşire dacă nrIncercari > nrMaxIncercari, nrIncercari la ieşire altfel, unde nrIncercari = numărul de încercări de la a treia cerinţă;
  4. Dacă (C4 == 1): nrDrumuri = numărul de drumuri valide sigure;
NU se lasă rând liber pentru Ci == 0. La ieşire vor fi atâtea rânduri câte valori ale indicatorilor (Ci) sunt 1.

Exemple

Punctul de plecare: Colţul de la baza piramidei este treapta notată cu 7.

Punctul de sosire: Colţul din vârful piramidei este treapta notată cu 1.

Faraonul ajunge pe o “margine” a hărţii când ajunge pe una din treptele cu valorile 5, 2, 4 sau 9.

matricea asociată acestei hărţi este:

1 4 9
2 3 8
5 6 7

Intrare pentru al doilea desen:

1 1 1 1
3
24
2 4 35
1 5 6
3 20 7
4

Iesire:

21
21
0
2

Explicaţii:

Toate drumurile valide (drumuri pe care poate merge faraonul) sunt:

7->20->3->1->2 Suma = 33 > 24; nesigur
7->20->5->1->2 Suma = 35 > 24; nesigur
7->20->5->4->2 Suma = 38 > 24; nesigur
7->6->5->1->2 Suma = 21 <= 24; sigur
7->6->5->4->2 Suma = 24 <= 24; sigur
7->6->35->4->2 Suma = 54 > 24; nesigur

Dintre cele 6 drumuri, doar 2 sunt sigure (afişat 2 pe ultimul rând la ieşire).

Observam că, pentru acest exemplu, alegerea optimului local duce la acelaşi rezultat cu optimul global (S1 = S2 = 21, afişat pe rândurile 1 şi 2).

Primele 12 valori obţinute la apelul rand() % 2 sunt: 1 1 0 1 0 1 1 1 1 0 0 1. De fapt, veţi ajunge să generaţi numai primele 9 valori (numai de atât aveţi nevoie pentru 4 simulări) pe acest exemplu, după cum urmează:

Prima încercare de drum (primele 2 apeluri rand: 1 1):
poziţia = 7, opţiuni = 6 şi 20. SUS -> 6.
poziţia = 6, opţiuni = 5 şi 35. SUS -> 35. (Implicit 35->4->2)
Soluţia: 7->6->35->4->2 nesigur
A doua încercare de drum (urmatoarele 3 apeluri rand: 0 1 0):
poziţia = 7, opţiuni = 6 şi 20. STANGA 20.
poziţia = 20, opţiuni = 3 şi 5. SUS 5.
poziţia = 5, opţiuni = 1 şi 4. STANGA 1. (Implicit 1->2)
Soluţia: 7->20->5->1->2 nesigur
A treia încercare de drum(urmatoarele 2 apeluri rand: 1 1):
Aceeaşi situaţie ca la prima incercare
Solutia: 7->6->35->4->2 nesigur
A patra încercare de drum(urmatoarele 2 apeluri rand: 1 1):
Aceeaşi situaţie ca la prima încercare
Solutia: 7->6->35->4->2 nesigur

Deci: nu am găsit niciun drum sigur după nrMaxIncercari = 4 încercări (afişat 0 pe rândul 3).

Variaţii la intrare

Dacă primul rând al intrării era 1 0 1 0, atunci la ieşire ar fi fost doar 2 rânduri (pentru cerinţa 1 şi pentru cerinţa 3). Adică, pentru aceleaşi valori în matrice:
21
0

Reguli pentru rulare

Comanda pentru execuţie va fi de forma: ./comoara f1 f2
  • f1 = fişierul cu datele de intrare
  • f2 = fişierul de ieşire cu rezultatele cerute
  1. C1 va fi mereu 1 (prima cerinţă va fi cerută pentru toate cazurile de testare).
  2. C4 va fi 1 numai pentru testele bonus (30p).
  3. Pentru 10p, numai C1 va fi 1.
  4. Pentru alte 20p, numai C1 şi C2 vor fi 1.
  5. Pentru alte 20p, numai C1 şi C3 vor fi 1.
  6. Valorile citite de la intrare şi sumele drumurilor vor fi mereu numere naturale din intervalul [0; 1013].
  7. Pentru 80p, orice drum va avea suma mai mică de 109.
  8. Pentru toate testele normale, 1 < n < 100 (pentru toate testele bonus, 1 < n < 12).

Reguli pentru trimitere

  1. Arhiva temei va avea numele GrupaSerie_Nume_Prenume_TemaNr.zip și va fi încărcată pe vmchecker, unde vă puteți loga folosind credențialele de pe acs.curs
  2. Ea va conține (direct în rădăcină):
    • un fişier numit comoara.c sau comoara.cpp
    • Makefile-ul (cu regulile make pentru executabilul comoara și clean)
    • fișierul README în care va fi descrisă soluția problemei
  3. Dacă soluția voastră nu compilează, dar ideea este bună și trimiteți o încercare de implementare, puteți primi până la 20p
  4. Temele care vor fi copiate vor primi 0p