Sunteți pe pagina 1din 7

2.

Metoda nainte
Problema triunghiului
Se consider un triunghi de numere naturale format din n linii. Prima linie conine
un numr, a doua dou numere, ... ,ultima n numere naturale. Cu ajutorul acestui
triunghi se pot forma sume de numere naturale n felul urmtor:
se pornete cu numrul din linia 1;
succesorul unui numr se afl pe linia urmtoare plasat sub el (aceeai
coloan) sau pe diagonal la dreapta (coloana crete cu 1).
Care este cea mai mare suma care se poate forma astfel i care sunt numerele
care o alctuiesc?

Exemplu: n=4

2
3 5
6 3 4
56 14

Se pot forma mai multe sume:


S1=2+3+6+5=16;
S2=2+5+4+1=12;
S k =2+3+6+6=17 (care este i suma maxim).
Observm c se pot forma 2 n 1 sume de acest fel. A le lua n consideraie pe toate
pentru a gsi valoarea maxim nu este eficient, timpul cerut de o astfel de rezolvare este
O(2 n ) . Pentru etapa i se trateaz linia i a triunghiului.
Fie un ir de n numere (care respect condiiile problemei i care formeaz
suma maxim). n acest ir, considerm numrul care a fost preluat de pe linia i.
Numerele ntre i+1 i n, formeaz o sum maxim n raport cu sumele care se pot forma
ncepnd cu numrul preluat de pe linia i (contrar, se contrazice ipoteza). n aceast
situaie se poate aplica programarea dinamic, metoda nainte.
Vom forma un triunghi, de la baz ctre vrf, cu sumele maxime care se pot
forma cu fiecare numr. Dac am citit triunghiul de numere ntr -o matrice T i
calculm sumele ntr-o matrice C vom avea relaiile urmtoare:
C[n,1] : T [n,1]
C[n,2] : T [n,2]
C[n, n] : T [n, n]
Pentru linia i (i<n), cele i sume maxime care se obin astfel:
C[i, j ] max{ T [i, j ] C[i 1, j ], T [i, j ] C[i 1, j 1]},
i {1,2,..., n 1}, j {1,..., i}
S rezolvm problema propus ca exemplu.
Linia 4 a matricei C va fi linia n a matricei T:
5, 6, 1, 4
Linia 3 se calculeaz astfel:
C[3,1] max{6 5,6 6} 12
C[3,2] max{3 6,3 1} 9
C[3,3] max{4 1,4 4} 8
Linia 2:
C[2,1] max{ 3 12 ,3 9} 15
C[2,2] max{ 5 9,5 8} 14
Linia 1:
C[1,1] max{2 15,2 14} 17
Aceasta este i cea mai mare sum care se poate forma. Pentru a tipri numerele
luate n calcul se folosete o matrice numit DRUM n, care fiecare i {1,...,n 1} i
j {1,...i} se reine coloana n care se gsete succesorul lui T[i,j].
Programul Pascal este:
Program Triunghi;
uses crt;
type matrice=array[1..100,1..100] of integer;
var n,i,j:integer; t,c,drum:matrice;
begin
clrscr;
Write('Introdu numarul de linii a triunghiului n=');
read(n);
for i:=1 to n do
for j:=1 to i do
begin
Write('t[',i,',',j,']=');
readln(t[i,j]);
end;
Writeln('Triunghiul este');
for i:=1 to n do
begin
for j:=1 to i do
Write(t[i,j]);
writeln;
end;
for j:=1 to n do
c[n,j]:=t[n,j];
for i:=n-1 downto 1 do
for j:=1 to i do
if c[i+1,j]>c[i+1,j+1]
then
begin c[i,j]:=t[i,j]+c[i+1,j];drum[i,j]:=j;end
else
begin c[i,j]:=t[i,j]+c[i+1,j+1];drum[i,j]:=j+1;end;

writeln('suma este:',c[1,1]);
i:=1;j:=1;
while i<=n do
begin
write(t[i,j]:3);
j:=drum[i,j];
i:=i+1;
end;
readkey;
end.

Rezultatul rulrii programului este:


Problema scrii cu n trepte
Un om dorete s urce o scar cu N trepte (N dat la tastatur). El poate urca una sau dou trepte
la un moment. Fiind o fire curioas, omul nostru i pune problema n cte moduri poate urca
aceast scar.
Rezolvare: Acesta este unul din puinele exemple n care optimul nu este foarte vizibil. S
gndim intuitiv n felul urmtor: suntem pe treapta i, nu are importan care este aceia. Ca s
ajungem aici, nainte am clcat ori pe treapta i-1 i de acolo am fcut un pas de o treapt, ori am
clcat pe treapta i - 2 i am fcut un pas de dou trepte. Ce scrie mai sus este adevrat pentru c
omul nu poate face dect dou transformri: un pas de o treapt sau un pas de dou trepte.
Deci s notm cu A[i] numrul de moduri n care se poate ajunge la treapta i, oricare ar fi
acesta. Acest numr este egal cu numrul de moduri de a ajunge la treapta i, treapta i - 1 (adic
A [i - 1) plus numrul de moduri de a ajunge la i - 2 (adic A [i - 2]). Am numrat deja toate
variantele n care se poare ajunge la treapta i: A[i]=A [i 1]+ A [i - 2].
Pe prima treapt putem ajunge ntr-un singur fel, un pas simplu: A[1]=1. Pe a doua
treapt putem ajunge n dou feluri: un pas simplu urmat de altul simplu, sau un pas dublu, deci
A[2]=2. De la treapta a treia ncolo folosim relaia A[i]=A [i - 1]+ A [i - 2]. Dup cum sa vede,
aceasta este de fapt irul Fibonacci n una din aplicaiile sale "drgue".
Ordinul de complexitate al algoritmului este N.
Programul Pascal este:
program scara;
uses crt;
const nmax=100;
var i,n:integer;
a:array [1..nmax] of longint;
begin
clrscr;
write('n=');
readln(n);
a[1]:=1;
a[2]:=2;
for i:=3 to n do
a[i]:=a[i-1]+a[i-2];
writeln('omul poate urca scara in ',a[n],' moduri.');
readkey;
end.

Rezultatul realizrii programului:


Subir cresctor de lungime maxim
Se consider un vector cu n elemente ntregi. Se cere sa se tipreasc cel mal lung
subir cresctor al acestuia.
Exemplu: Pentru n=5. Avem vectorul V=(4,1,7,6,7). n acest caz, subirul tiprit va fi:
4,7,7.
Problema se poate rezolva pornind de la ideea de a calcula, pentru fiecare element al
vectorului lungimea celui mai lung subir cresctor care se poate forma ncepnd cu el. n
final este selectat elementul din vector cu care se poate forma cel mai lung subir
cresctor i acesta este listat.
n continuare, este prezentat modul de gndire prin care a fost obinut aceasta
idee. Presupunem c cel mai lung subir care se poate forma cu elementul care se afl pe
poziia k a vectorului este Vi1 , Vi 2 ,..., Vik ,..., Vip unde i1 , i2 ,..., ik ,..., i p sunt indicii termenilor

subirului relativ la vectorul dat. Se observ c, n aceast situaie Vk ,..., Vip este lungimea

celui mai lung subir cresctor care se poate forma ncepnd cu elementul V k Acest fapt se
demonstreaz prin reducere la absurd. Presupunem c se poate forma un subir cresctor
de lungime mai mare ncepnd cu elementul V k . Atunci Vi1 , Vi 2 ,..., Vik ,..., Vip nu este cel mai

lung subir care se poate forma i conine elementul V k , deci ipoteza este contrazis. Am

verificat astfel principiul 1 al programrii dinamice, deci fiecare decizie D1 va depinde de

deciziile Di 1 , Di 2 ,..., D p . Astfel, se aplic metoda nainte. Dac notm cu L(k )

lungimea celui mai lung subir cresctor ce se poate forma ncepnd cu elementul k al
vectorului, vom avea relaiile:
L(k ) { 1 max L(i) V (i) V (k ) , i {k 1,...,n}}, k {1,2,...,n}
n practic, vom folosi un vector L cu n componente, unde L(k) are semnificaia
explicat. Pentru exemplul nostru vom avea: L = ( 3 , 3 , 2 , 2 , 1 ) . Componentele vectorului L
au fost calculate astfel:
cel mai lung subir care se poate forma cu elementul 7, aflat pe ultima
poziie, are lungimea 1;
cel mai lung subir care se poate forma cu elementul 6 aflat pe poziia
4 are lungimea 2, (1+L(5)), pentru c pe poziia 5 se gsete elementul
7 care este mai mare dect 6;
cel mai lung subir care se poate forma cu elementul aflat pe poziia 3
are lungimea 2, (1+L(5)) pentru c 7 este egal cu 7;
algoritmul continu n acest mod pn se completeaz L(1).
Dup aceasta se calculeaz maximul dintre componentele lui L, iar cel mai lung
subir cresctor format din elementele vectorului V va avea lungimea dat de acest
maxim.
Pentru a lista efectiv acel subir de lungime maximal se procedeaz astfel:
se caut maximul din vectorul L precum i indicele t, la care se gsete
acest maxim;
se listeaz V(t);
se gsete i se listeaz primul element care este mai mare sau egal
cu V(t) i are lungimea mai mic cu 1 (max-1), se actualizeaz valoarea
max cu max-1;
algoritmul continu pn cnd se epuizeaz toate elementele subirului.
Programul Pascal este:
program Subsir_crec;
{Determinarea celui mai mare subsir crescator}
uses crt;
type vector=array[1..50] of integer;
var v,l:vector;
n,i,k,max,t:integer;
begin
clrscr;
write('Introdu numarul de elemente ale sirului V=');
readln(n);
for i:=1 to n do
begin
write('v[',i,']= ');
readln(v[i]);
end;
writeln('Sirul introdus este:');
for i:=1 to n do
write(v[i]:5);
writeln;

l[n]:=1;
for k:=n-1 downto 1 do
begin
max:=0;
for i:=k+1 to n do
if (v[i]>=v[k]) and (l[i]>max) then max:=l[i];
l[k]:=1+max;
end;
max:=l[1];
t:=1;
for k:=1 to n do
if l[k]>max then
begin
max:=l[k];
t:=k;
end;
writeln('Subsirul crescator de lungime maxima are ',max,' elemente:');
write(v[t]:5);
for i:=t+1 to n do
if (v[i]>v[t]) and (l[i]=(max-1)) then
begin
write(v[i]:5);
max:=max-1;
end;
readkey;
end.

Rezultatul rulrii programului este:

S-ar putea să vă placă și