suma in triunghi
DESCRIPTION
suma in triunghiTRANSCRIPT
2. Sumă în triunghi
Sa considerăm un triunghi format din n linii (1<n100), fiecare linie conţinând numere întregi
din domeniul [1,99], ca în exemplul următor:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
Problema constă în scrierea unui program care să determine cea mai mare sumă de numere aflate
pe un drum între numărul de pe prima linie şi un număr de pe ultima linie. Fiecare număr din acest
drum este situat sub precedentul, la stânga sau la dreapta acestuia. (IOI, Suedia 1994)
Soluţie
1. Vom reţine triunghiul într-o matrice pătratică T, de ordin n, sub diagonala principală.
Subproblemele problemei date constau în determinarea sumei maxime care se poate obţine din
numere aflate pe un drum între numărul T[i][j], până la un număr de pe ultima linie, fiecare
număr din acest drum fiind situat sub precedentul, la stânga sau la dreapta sa. Evident,
subproblemele nu sunt independente: pentru a calcula suma maximă a numerelor de pe un drum de
la T[i][j] la ultima linie, trebuie să calculăm suma maximă a numerelor de pe un drum de la
T[i+1][j] la ultima linie şi suma maximă a numerelor de pe un drum de la T[i+1][j+1] la
ultima linie.
2. Pentru a reţine soluţiile subproblemelor, vom utiliza o matrice suplimentară S, pătratică de ordin n,
cu semnificaţia
S[i][j]= suma maximă ce se poate obţine pe un drum de la T[i][j] la un element de pe
ultima linie, respectand condiţiile problemei.
Evident, soluţia problemei va fi S[1][1].
3. Relaţia de recurenţă care caracterizează substructura optimală a problemei este:
S[n][i]=T[n][i], i{1,2,...,n}
S[i][j]=T[i][j]+max{S[i+1][j], S[i+1][j+1]}
4. Rezolvăm relaţia de recurenţă în mod bottom-up:
int i, j;
for (i=1; i<=n; i++) S[n][i]=T[n][i];
for (i=n-1; i>0; i--)
for (j=1; j<=i; j++)
{S[i][j]=T[i][j]+S[i+1][j];
if (S[i+1][j]<S[i+1][j+1])
S[i][j]=T[i][j]+S[i+1][j+1]);}
Exerciţiu
Afişaţi şi drumul în triunghi pentru care se obţine soluţia optimă.
Programul C++
1. #include<fstream> 2. #include<iostream> 3. using namespace std; 4. 5. int n,m,T[101][101],S[101][101]; 6. fstream fin("triunghi.in",ios::in), 7. fout("triunghi.out",ios::out); 8. 9. void citire() 10. { 11. int i,j; 12. fin>>n; 13. for(i=1;i<=n;i++) 14. for(j=1;j<=i;j++) 15. { 16. fin>>T[i][j]; 17. } 18. } 19. 20. void triunghi() 21. { 22. int i,j; 23. for (i=1; i<=n; i++) 24. S[n][i]=T[n][i]; 25. for (i=n-1; i>0; i--) 26. for (j=1; j<=i; j++) 27. { 28. S[i][j]=T[i][j]+S[i+1][j]; 29. if (S[i+1][j]<S[i+1][j+1]) 30. S[i][j]=T[i][j]+S[i+1][j+1]; 31. } 32. } 33. 34. void tipar() 35. { 36. int i,j; 37. for(i=1;i<=n;i++) 38. { 39. for(j=1;j<=i;j++) 40. cout<<S[i][j]<<" "; 41. cout<<endl; 42. } 43. } 44. int main () 45. { 46. citire(); 47. triunghi(); 48. tipar(); 49. fout<<S[1][1]; 50. fin.close(); 51. fout.close(); 52. return 0; 53. }