Documente Academic
Documente Profesional
Documente Cultură
float *j;
int alt_numar;
alt_numar = *int_pointer;
Acest cod plaseaza valoarea din variabila numar in
alt_numar. De aceea alt_numar va avea valoarea 100.
Valoarea 100 este stocata la locatia 2000, locatie care a fost
stocata in pointerul int_pointer.
Va puteti gandi la * ca fiind "de la adresa".
void main()
{
int i=1, j=5, *p=&i;
*p=2;
(*(p=&j))++;
printf(“i=%d j=%d\n”, i, j);
}
Prin *p=2; se atribuie lui i valoarea 2. Apoi se atribuie lui p adresa lui j, dupa care se
incrementeaza continutul lui p,adica variabila j.Astfel programul afiseaza i=2, j=6.
#include <stdio.h>
void main(){
int i, j;
int *pInt;
i = 5;
j = 2;
pInt = &i;
printf("*pInt are valoarea %d\n",*pInt);
pInt = &j;
printf("*pInt are valoarea %d\n",*pInt);
}
Dupa ce compilati si rulati codul de mai sus va trebui sa vedeti
doua linii. Pe prima linie ne spune ca *pInt are valoarea 5 iar pe
cea de-a doua linie afisata ne spune ca *pInt are valoarea 2.
void main(){
int i;
char sir[] = "abcdefghi";
char *pChar;
pChar = sir;
}
Codul de mai sus declara variabila sir si o initializeaza cu sirul de
caractere "abcdefghi". Mai jos declaram un pointer, pChar, care
memoreaza date de tip char.
Mai jos punem in pChar adresa sirului de caractere declarat mai
sus ( sir ).
Initializarea cu adresa unei variabile se realizeaza prin:
tip variabila, *var_pointer;
var_pointer=&var;
Valoarea de la adresa indicata de pointer este data de:
*var_pointer
Spatiul ocupat de o variabila pointer se poate determina prin:
sizeof( var_pointer).
Pentru tiparirea valorii unui pointer se foloseste prototipul %p
valoarea fiind afisata sub forma a 4 cifre hexazezimale.
- fişier de intrare
- fişier de ieşire
1
- al doilea nivel se realizează prin intermediul unor
proceduri specializate de prelucrare a fişierelor care
utilizează structuri speciale de tip FILE (fişier).
Acesta este nivelul superior de prelucrare a
fişierelor.
#include <io.h>
#include <fcntl.h>
Apelul:
df = open (lista_par);
2
Exemple:
II. Crearea
- crearea unui fişier nou
int creat (const char * calea, int mod);
#include <io.h>
#include <stat.h>
III. Citirea
unde
3
df este descriptorul de fişier
IV. Scrierea
int write (int df, void * zona, unsigned lung);
V. Poziţionarea în fişier
long lseek (int df, long deplasament, int origine);
4
Exemplu de utilizare a funcţiilor prezentate:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <io.h>
#include <sys\stat.h>
void main()
{ clrscr();
union unr
{
float nr;
char tnr[sizeof(float)];
};
union unr nrcit;
int df1,df2;
int i,j;
/* se deschid fisierele fis1.dat si fis2.dat in creare
cu acces in citire-scriere
*/
if((df1=creat("fis1.dat",S_IWRITE|S_IREAD))==-1)
{
printf("nu se poate deschide fisierul fis1.dat in creare \n");
exit(1);
}
if((df2=creat("fis2.dat",S_IWRITE|S_IREAD))==-1)
{
printf("nu se poate deschide fisierul fis2.dat in creare \n");
exit(1);
}
5
/* se citeste sirul de numere si se depune in fisiere */
j=1;
printf("tastati nr. separarte prin caractere albe \n");
while((scanf("%f",&nrcit.nr))==1)
{
if(j&1)
{
if(write(df1,nrcit.tnr,sizeof(float))!=sizeof(float))
{
printf("eroare la crearea fisierului fis1.dat \n");
exit(1);
}
}
else /* j este par */
if(write(df2,nrcit.tnr,sizeof(float))!=sizeof(float))
{
printf("eroare la crearea fisierului fis2.dat \n");
exit(1);
}
j++;
}
/* s-a terminat crearea, se inchid fisierele */
if(close(df1)<0)
{
printf("eroare la inchiderea fisierului fis1.dat \n");
exit(1);
}
if(close(df2)<0)
{
printf("eroare la inchiderea fisierului fis2.dat \n");
exit(1);
}
/* se deschide fis1.dat si se afiseaza continutul */
if((df1=open("fis1.dat",O_RDONLY))==-1)
{
printf("nu se poate deschide fisierul fis1.dat \n");
6
exit(1);
}
while((i=read(df1,nrcit.tnr,sizeof(float)))>0)
printf("%g\t",nrcit.nr);
if(i<0)
{
printf("eroare la citirea fisierului \n");
exit(1);
}
close(df1);
printf("\n");
getch();
/* la fel pentru fis2.dat */
if((df2=open("fis2.dat",O_RDONLY))==-1)
{
printf("nu se poate deschide fisierul fis2.dat \n");
exit(1);
}
while((i=read(df2,nrcit.tnr,sizeof(float)))>0)
printf("%g\t",nrcit.nr);
if(i<0)
{
printf("eroare la citirea fisierului \n");
exit(1);
}
close(df2);
printf("\n");
getch();
}
7
Nivelul superior de prelucrare a fişierelor
Fiecărui fişier i se ataşează o structură de tip FILE, tip
definit în fişierul stdio.h.
Deschiderea unui fişier
1
Închiderea unui fişier
Exemplu :
Fiind dat un fişier text, să se determine şi să se afişeze câte
litere mari conţine fişierul.
#include <stdio.h>
#include <conio.h>
void main()
{ clrscr();
FILE *df;
char c;
int n=0;
df=fopen("text.txt","r");
// if((df=fopen("c:\\text.txt","rt"))= =0)
//{ printf("Fisierul nu poate fi deschis in citire !");
// exit(1);
//}
while(!feof(df))
{
c=fgetc(df);
if (c>='A' && c<='Z') n++;
}
fclose(df);
printf("in fisier sunt %d litere mari \n",n);
getch();
}
2
Citirea şi scrierea înregistrărilor care sunt şiruri de
caractere.
- funcţiile fgets şi fputs
char * fgets (char *s, int n, FILE *pf);
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
void main()
{ clrscr();
FILE *df;
char linie[256],liniemax[256];
int lmax=0,nrlinii=0;
// df=fopen("text.txt","r");
if((df=fopen("c:\\text.txt","rt"))= =0)
{ printf("Fisierul nu poate fi deschis in citire !");
exit(1);
}
while(!feof(df))
{
fgets(linie,256,df);
nrlinii++;
3
if (lmax<strlen(linie))
{
lmax=strlen(linie);
strcpy(liniemax,linie);
}
}
fclose(df);
//if(close(df1)<0)
//{
//printf("eroare la inchiderea fisierului fis1.dat \n");
//exit(1);
//}
printf("fisierul are %d linii",nrlinii);
printf("\n ultima linie de lungime maxima este: %s\n",
liniemax);
getch();
}
4
Eliberarea zonei tampom folosite de respectivul fişier.
”Curăţirea” (sau vidarea) zonei tampon se realizează cu
funcţia fflush, care are prototipul :
int fflush ( FILE *pf ) ;
5
Prelucrarea fişirelor binare
6
/* Tratarea fis. la nivel superior Prelucrarea fisierelor
binare
*/
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#define MAX 30
typedef struct
{
char titlu[MAX];
char autor[12];
} articol;
articol carte;
char Numefis[30];
char Numenou[30];
void creare (void);
void adaug_sf(void);
void modificare(void);
void listare(void);
void main()
{ char op;
strcpy(Numefis,"C:\\carti.txt");
strcpy(Numenou,"C:\\carti1.txt");
do
{
7
clrscr();
printf("\n OPERATII ASUPRA CARTILOR\n");
printf("C. Creare fisier\n");
printf("A. Adaugarea unei carti la sfarsit\n");
printf("M Modificare carte\n");
printf("L Afisare carti\n");
printf("E Terminare program\n\n\n");
printf(" Introduceti optiunea:");
scanf("%c",&op);op=toupper(op);
switch (op)
{
case 'C':creare();break;
case 'A':adaug_sf();break;
case 'M':modificare();break;
case 'L':listare();break;
case 'E':printf("Terminare program\n");break;
default :printf("Optiune gresita!\n");break;
}/* switch */
printf("Tastati ENTER!"); fflush(stdin);
getch();
}
while (op != 'E');
}/* main */
8
/* printf("\nDati numele si calea fis. care il creati:");
fflush(stdin);scanf("%s",Numefis);*/
/* se deschide fis in scriere */
pf=fopen(Numefis,"wb");
if (pf==NULL)
{
printf("Nu se poate crea fisierul\n");
exit(1);
};
do
{
printf("\n Introduceti titlul:");
fflush(stdin);gets(carte.titlu);
printf("\n Introduceti autorul:"); fflush(stdin);
gets(carte.autor);
fwrite(&carte,sizeof(carte),1,pf);
printf("Mai adaugati(D/N):");
fflush(stdin);c=getche();c=toupper(c);
} while(c=='D');
fclose(pf);
}/* creare */
void adaug_sf(void)
{
FILE *pf;
int i,n;
clrscr();
/* printf("\nDati numele si calea fis. in care adaugati:");
scanf("%s",Numefis); */
/* se deschide fis pentru adaugare */
9
if ((pf=fopen(Numefis,"a"))==0)
{
printf("Nu se poate deschide fisierul\n");
exit(1);
}
printf("\n Introduceti titlul:");
fflush(stdin);gets(carte.titlu);
printf("\n Introduceti autorul:"); fflush(stdin);
gets(carte.autor);
fwrite(&carte,sizeof(carte),1,pf);
fclose(pf);
}/* adaug_sf */
void modificare(void)
{
FILE *pf;
int i,sant=0;
long n,m;
char numedat[30];
char titlu1[30];
char autor1[30];
clrscr();
/* printf("\nDati numele si calea fis. care-l modificati:");
fflush(stdin);scanf("%s",Numefis); */
/* se deschide fis pentru citire */
pf=fopen(Numefis,"r+");
if (pf==0)
{
printf("Nu se poate modifica fisierul\n");
exit(1);
}
10
printf("\nTitlul de modificat= ");
fflush(stdin);gets(numedat);
while(!feof(pf))
{
n=ftell(pf); /* n contine poz. curenta a point. de fis. */
i=fread(&carte,sizeof(carte),1,pf);
/* point de fis. indica acum art. urmator, celui citit. */
if(i!=0)
{
if(strcmp(carte.titlu,numedat)==0)
{
/* Acum point. de fisier = n+sizeof(carte) oct. */
printf("\n Articolul de modificat:");
printf("\n titlul: %s",carte.titlu);
printf("\n autor:%s",carte.autor);
printf("\nNoul titlu= ");fflush(stdin);gets(titlu1);
printf("\nNoul autor= ");fflush(stdin);gets(autor1);
strcpy(carte.titlu,titlu1);
strcpy(carte.autor,autor1);
/* n contine pozitia in fisier a articolului de modificat */
/* repun point. de fis.pe poz. unde fac modific,indicata de
n */
fseek(pf,n,0);
fwrite(&carte,sizeof(articol),1,pf);
/* Acum point. de fisier = n+sizeof(carte) oct. */
sant=1;
}
}
}/* while */
if (sant==0)
printf("\n\n Nu am gasit articolul in fisier\n\n");
11
fclose(pf);
}/* modificare */
void listare(void)
{
FILE *pf;
int i,n;
clrscr();
/* printf("\nDati numele si calea fis.de listat:");
fflush(stdin);scanf(Numefis); */
pf=fopen(Numefis,"rb");
if(pf==0)
{
printf("\n nu pot deschide fis\n");
exit(1);
}
printf("\n Lista cartilor:\n");
while(!feof(pf))
{
i=fread(&carte,sizeof(carte),1,pf);
if(i!=0)
{
printf("\n titlu: %s",carte.titlu);
printf("\n autor:%s",carte.autor);
}
};
fclose(pf);
}
12
METODE DE SORTARE
Sortare:
- internă
- externă
- Simplitate
- Eficientă
- Naturaleţe.
- Stabilitate.
1
1. SORTARE PRIN INTERSCHIMBARE
Interschimbari (x[1..n])
REPETA
|| se parcurge şirul şi dacă 2 elemente vecine nu sunt
|| în ordinea corectă, se interschimbă
PÂNĂCÂND <nu mai este necesară nici o interschimbare>
Variante
Interschimbari1 (x[1..n])
PENTRU i=n,2 executa
|| PENTRU j=1, i-1 executa
|| DACA x[j]>x[j+i] atunci x[j] ¨ x[j+1]
Return (x[1..n])
2
Interschimbari2 (x[1..n])
REPETA
schimb=fals
PENTRU i=1,n-1 executa
|| DACA x[i]>x[i+i] atunci x[i] ¨ x[i+1]
schimb=adevarat
|| SFDACA
SFPENTRU
PÂNĂCÂND schimb=fals
Return (x[1..n])
Interschimbari3 (x[1..n])
m=n {la inceput se parcuge tot tabloul}
REPETA
t=0 { in t se retine cel mai mare indice
pentru care se face interschimbarea}
|| PENTRU i=1, m-1 executa
|| DACA x[i]>x[i+i] atunci x[i] ¨ x[i+1]
t=i
|| SFDACA
|| SFPENTRU
m=t
PÂNĂCÂND t<=1
Return (x[1..n])
3
2. SORTAREA PRIN INSERŢIE
Inserţie (x[1..n])
PENTRU i=2, n execută
|| inserează x[i] în subşirul x[1..i-1] astfel încât
|| x[1..i] să fie ordonat
Descrierea detaliată
Inserţie (x[1..n])
PENTRU i=2, n execută
|| j= i-1
|| aux=x[i]
|| CÂTTIMP aux<x[j] && j>=1 execută
x[j+1]=x[j]
j=j-1
|| x[j+1]=aux
SFPENTRU
Return (x[1..n])
4
- vectorul iniţial are elemente distincte; fiecare element
este inserat în locul corespunzător, în raport cu elementele
sortare anterior
- se consideră x[1]<=x[2]<=...x[j-1]
- se compară x[j] cu x[j-1], x[j-2],... până când se
determină că x[j] trebuie inserat între x[i] şi x[i+1]
- apoi se deplasează secvenţa x[i+1],...,x[j-1] cu o poziţie şi
se va introduce noul element în poziţia i+1
insertie2(x[1..n])
PENTRU i= 2, n executa
|| x[0]= x[i] { plasarea lui x[i] pe pozitia fanionului }
|| j= i- 1
||CATTIMP (x[0] < x[j]) executa
|| x[j + 1]= x[j]
|| j= j- 1
||SFCATTIMP
|| x[j + 1] =x[0] {inserarea val. fanion pe poz. adecvata}
SFPENTRU
Return(x[1..n)
5
3. SORTARE PRIN SELECŢIE
Selecţie (x[1..n])
PENTRU i=1, n-1 execută
|| se determină valoarea minimă din subşirul x[i..n]
|| şi se interschimbă cu x[i]
Descrierea detaliată
Selecţie (x[1..n])
PENTRU i=1, n-1 execută
|| k= i
|| PENTRU j=i+1, n execută
|| DACĂ x[k]>x[j] atunci k=j
|| SFDACĂ
|| SFPENTRU
|| DACĂ i∫ k atunci x[k] ¨ x[i]
|| SFDACĂ
SFPENTRU
Return (x[1..n])
6
4. SORTAREA PRIN NUMĂRARE
Numărare (x[1..n])
PENTRU j=2, n execută
|| se determină cîte elemente din subşirul x[1..j-1]
|| sunt mai mici decât fiecare x[j]
Descrierea detaliată
Numărare (x[1..n])
PENTRU i=1, n execută
|| contor[i] =1
SFPENTRU
PENTRU j=2, n execută
|| PENTRU i= 1, j-1 execută
|| DACĂ x[i]<x[j] atunci contor[j]=contor[j]+1
altfel contor[i]=contor[i]+1
|| SFDACĂ
|| SFPENTRU
SFPENTRU
PENTRU i=1, n execută
|| a[contor[i]] = x[i]
SFPENTRU
Return (a[1..n])
7
5. SORTARE PRIN INTERCLASARE
8
RECURSIVITATE
proces nume_proces(parametrii)
{
Calcul_iniţial
IF
Condiţie_oprire
THEN
Calcul_nerepetabil
ELSE
Calcul_repetabil
ENDIF
Calcul_final
}
void p( )
{ //functie recursiva
p(); //apel infinit
}
//apelul trebuie conditionat in una din variantele:
if(cond)
p();
while(cond)
p();
do
p()
while(cond);
1
Calculul n!
n!=(n-1)!*n
Varianta recursivă
1, n=0
f (n) =
n * f(n - 1), n >= 1
2
//afisarea unui sir de caractere in ordine inversa
#include <stdio.h>
#include <conio.h>
#include <string.h>
int n;
char s[100];
void afisare(int i)
{
if (i<n) afisare(i+1);
printf("%c",s[i]);
}
void main()
{ printf("sirul de caractere "); scanf("%s",s);
n=strlen(s);
printf("sirul are %d caractere \n",n);
afisare(0);
printf("\n");
getch();
}
3
Să se scrie o funcţie care determină valoarea pentru
combinări de n luate câte k, C kn .
Pentru k=0, Cn0 = 1, ∀n∈Ν şi avem relaţia de recurenţă
n
Cnk = Cnk−−11 .
k
#include <stdio.h>
#include <conio.h>
short n,k;
double comb(int n, int k)
{
if (k= =0) return 1;
else return n*comb(n-1,k-1)/k;
}
void main( )
{
printf("n="); scanf("%d",&n);
printf("k="); scanf("%d",&k);
printf("%d!=%lf\n", n, comb(n,k));
getch();
}
4
0
4
---
1 1
5 5
--- ---
2 2 2
6 6 6
--- --- ---
3 3 3 3
7 7 7 7
--- --- --- ---
1
1
5
--- 5
2 2
6 6
--- --- 15
3 3 3
7 7 7
--- --- --- 35
5
Algoritmi de căutare
Căutarea secvenţială
Cautare(v[1..n], k)
i=1
CÂTTIMP (i<=n şi v[i]∫k) execută i=i+1
SFCÂTTIMP
DACĂ (i§ n) ATUNCI cauta=true
ALTFEL cauta=false
SFDACĂ
SfCautare
1
Căutarea secvenţială într-un tablou ordonat
Cautare(v[1..n], k)
gata=false
gasit=false
CÂTTIMP (i<=n şi not gata) execută
DACĂ (v[i]= k) ATUNCI
gata=true
gasit=true
ALTFEL
DACĂ v[i]>k ATUNCI
gata=true
ALTFEL
i=i+1
SFDACĂ
SFDACĂ
SFCÂTTIMP
DACĂ (i>n sau not gasit) ATUNCI “cautare fara succes”
ALTFEL “cautare cu succes”
SFDACĂ
SfCautare
2
Căutarea binară
3
Fie v tabloul ordonat crescător v1 ≤ v2 ≤ ... ≤ vn .
Algoritmul pentru varianta iterativă
Caut(v[1..n], k)
inf=1
sup=n
ind=0
CÂTTIMP (inf § sup şi ind=0) execută
mij= (inf+sup)/2
DACĂ (v[mij]=k) ATUNCI ind=1
ALTFEL
DACĂ (v[mij]<k) ATUNCI inf=mij+1
ALTFEL sup=mij-1
SFDACĂ
SFDACĂ
SFCÂTTIMP
DACĂ (ind=1) ATUNCI return mij
ALTFEL return 0
SFDACĂ
SfCaut
4
Tehnica alegerii local optimale
Metoda Greedy
Principiul tehnicii
Fie A ={a1, a2,..., an} un set fnit de elemente (nu neapărat distincte).
Să se determine S = (s1, s2, ..., sk) Õ A astfel încât S să satisfacă
anumite restricţii şi să optimizeze un criteriu.
1
Structura generală a algoritmului este:
greedy(A)
S= ∅
CÂTTIMP
("S nu este soluţie" & "există elemente neselectate în A")
execută
selectează a din A
dacă nu sunt încălcate restricţiile se adaugă a la S
SFCÂTTIMP
return S
2
O variantă a acestei proceduri este următoarea:
Problema rucsacului
3
Rezolvare:
În mod formal, problema cere de fapt să se maximizeze
n n
∑ p i xi supusă la restricţiile ∑ g i xi <=M, unde 0<=xi<=1 şi
i =1 i =1
n
soluţie optimă este o soluţie posibilă pentru care ∑ pi xi este
i =1
maxim.
Strategia care se aplică ia în considerare atât factorul de
greutate cât şi cel de profit. Astfel, vom aplica strategia
conform căreia se adaugă la fiecare pas obiectul care are
raportul pi / gi maxim. Dacă obiectele sunt aranjate astfel încât:
p1 / g1 ≥ p2 / g2 ≥…≥ pn / gn
4
Algoritmul corespunzător acestei strategii este:
5
Problema spectacolelor.
Într-o sală, într-o zi trebuie planificate n spectacole. Pentru fiecare
spectacol se cunoaşte intervalul de timp în care se desfăşoară (ora de
început , ora de sfârşit).
Se cere, să se planifice un număr maxim de spectacole astfel încât să
nu se suprapună spectacolele.
6
(Problema monedelor) Fiind date monede de valori v1, v2,...,vn şi o
sumă C, să se determine numărul minim de monede necesar pentru a
acoperi suma C. Se presupune că există un număr nelimitat de
monede.
Monede(v[1..n],C)
OrdonareDescrescatoare[v[1..n])
Pentru i=1,n executa S[i]=0
SfPentru
i=1
CatTimp C>0 si i<=n executa
S[i] = [ C / v[i] ]
C = C mod v[i]
i=i+1
SfCatTimp
Daca C=0 atunci Return S[1..n]
altfel “nu s-a gasit solutia”
SfDaca
7
TEHNICI DE REDUCERE SI DIVIZARE
Putere1(x, n)
p=1;
PENTRU i=1, n executa
|| p=p*x;
SFPENTRU
Return p
Putere2(x, m)
p=x;
PENTRU i=1, m executa
|| p=p*p;
SFPENTRU
Return p
Putere3(x, n)
DACA n=2 ATUNCI Return x*x;
ALTFEL
|| p=Putere3(x, n/2);
|| Return p*p
SFDACA
1
Tehnica Divide et Impera
Descrierea metodei
DivI(p,q)
a[1,n];
n, p, q, m; 1<=p; q<=n
DACA MIC(p,q)
ATUNCI Return G(p,q)
ALTFEL
|| m=DIVIDE(p,q); p<=q
|| Return (combină (DivI(p,m), DivI(m+1,q))
SFDACA
2
Exemplu : determinarea maximului dintr-o secvenţă finită
de valori reale.
Maxim (x[s..d])
DACA s=d ATUNCI max=x[s]
ALTFEL
|| max1= maxim(x[1..n/2])
|| max2= maxim(x[n/2+1..n])
|| DACA max1<max2 ATUNCI max=max2
ALTFEL max=max1
|| SFDACA
|| SFDACA
Return max
3
Dacă n=2, mutările care rezolvă problema sunt: ac, ab, cb.
În cazul n>2, problema este echivalentă cu:
1. mutarea a n-1 discuri de pe tija a pe tija c, utilizând ca
tijă intermediară tija b;
2. mutarea discului rămas pe tija a, pe tija b;
3. mutarea a n-1 discuri de pe tija c pe tija b, utilizând ca
tijă intermediară tija a.
ab dacă n = 1
H (n, a, b, c) =
H (n − 1, a, c, b), ab, H(n - 1, c, b, a) dacă n > 1
De exemplu:
H(3,a,b,c)=H(2,a,c,b),ab,H(2,c,b,a)=
=H(1,a,b,c),ac,H(1,b,c,a),ab,H(1,c,a,b),cb,H(1,a,b,c)=
4
Metoda interclasării
5
Pentru rezolvarea problemei se vor utiliza 3 funcţii:
- o funcţie sort care va sorta un vector de maxim 2
elemente;
- o funcţie intercl care interclasează rezultatele şi
- o funcţie divimp care implementează strategia tehnicii
Divide et Impera.
6
Quicksort (sortarea rapidă)
Ex.
(3,1,2,7,5,4,8) ai<=aj
pentru i=1,2,…,q
j=q+1,q+2,…,n
7
QuickSort1(a[li..ls])
Daca li<ls atunci
q=partitie1(a[li..ls])
QuickSort(a[1..q-1])
QuickSort(a[q+1..n])
SfDaca
Return a[li..ls]
QuickSort2(a[li..ls])
Daca li<ls atunci
q=partitie2(a[li..ls])
QuickSort(a[1..q])
QuickSort(a[q+1..n])
SfDaca
Return a[li..ls]
Obs.
8
partitie1(a[li..ls])
v=a[ls] // alegere pivot
i=li-1 // indice pentru parcurgere sir de la stanga la dreapta
j=ls // indice pentru parcurgere sir de la dreapta la stanga
CatTimp i<j executa
Repeta
i=i+1
PanaCand a[i]>=v
Repeta
j=j-1
PanaCand a[j]<=v
Daca i<j atunci a[i]¨ a[j]
SfDaca
SfCatTimp
a[i] ¨ a[ls]
Return i
partitie1(a[li..ls])
v=a[ls] // alegere pivot
i=li-1 // indice pentru parcurgere sir de la stanga la dreapta
j=ls+1 // indice pentru parcurgere sir de la dreapta la stanga
CatTimp i<j executa
Repeta
i=i+1
PanaCand a[i]>=v
Repeta
j=j-1
PanaCand a[j]<=v
Daca i<j atunci a[i]¨ a[j]
SfDaca
SfCatTimp
a[i] ¨ a[ls]
Return j
9
Metoda Backtracking
-mulţimile Ai, i=1…n, sunt mulţimi finite, card(Ai) = ai, iar elementele
lor se consideră că se află într-o relaţie de ordine bine stabilită;
Observaţii:
- x1,x2,…,xn pot fi la rândul lor vectori;
1
Descrierea metodei :
2
xk
…
…
x2
x1
3
Cu aceste notaţii rutina backtracking este următoarea:
void back()
{ int As;
k=1;
Init();
while (k>0)
{
do { } while ((As=Am_Succesor()) && !Valid());
if (As)
if (Solutie()) Tipar();
else { k++;
Init();
}
else k--;
}
}
4
Altă variantă a rutinei backtracking, în care funcţiile au parametrii de
intrare:
5
Cu aceste funcţii rutina backtracking devine:
void back()
{
int k;
int As, Ev;
k=1;
Init(st,k);
while (k>0)
{ do {
As=Am_Succesor(st,k);
if (As= =1) Ev=Valid(st,k);
} while ( (As= =1 && Ev= =0));
if (As)
if (Solutie(k)) Tipar();
else {
k++;
Init(st,k);
}
else k--;
}
}
6
Exemplul 1. Generarea permutărilor
#include <stdio.h>
#include <conio.h>
int st[10],n;
void Init(int st[], int k)
{
st[k]=0;
}
int Am_Succesor(int st[],int k)
{
if(st[k]<n)
{
st[k]++;
return 1;
}
else return 0;
}
int Valid(int st[],int k)
{
for(int i=1;i<k;i++)
if(st[i]= =st[k]) return 0;
return 1;
}
7
int Solutie(int k)
{
return k= =n;
}
void Tipar()
{
for(int i=1;i<=n;i++) printf("%d ",st[i]);
printf("\n");
}
void back()
{ int k, As, Ev;
k=1;
Init(st,k);
while (k>0)
{ do
{ As=Am_Succesor(st,k);
if (As==1) Ev=Valid(st,k);
} while ( (As==1 && Ev==0));
if (As)
if (Solutie(k)) Tipar();
else {
k++;
Init(st,k);
}
else k--;
}
8
}
void main()
{
clrscr();
printf("n="); scanf("%d",&n);
back();
getch();
}
Obs.
Două dame se găsesc pe aceeaşi diagonală dacă şi numai dacă este
îndeplinită condiţia:
|st(i) - st(j)|=|i-j| ,
(diferenţa, în modul, dintre linii şi coloane este aceeaşi).
În general, st(i)=k semnifică faptul că pe linia i dama ocupă poziţia k.
9
Metoda Backtracking
A[i,j]=1 sau 0
st[k] reprezentă culoarea ataşată ţării k.
1
void Tipar()
{
//for(int i=1;i<=n;i++) printf("tara %d are culoarea %d ",i,st[i]);
for(int i=1;i<=n;i++) printf(" %d ",st[i]);
printf("\n");
nr++;
}
void main()
{
clrscr();
printf("nr tari=");
scanf("%d",&n);
nr=0;
// matricea A reprezentand tarile cu vecinii se va completa
// tinand cont ca este simetrica
for (int i=1;i<=n;i++)
for (int j=1;j<=i-1;j++)
{ printf("a[%d,%d]=",i,j);
scanf("%d",&a[i][j]);
a[j][i]=a[i][j];
}
back();
printf("nr. solutiilor=%d",nr);
getch();
}
2
Exemplul 5. Problema plăţii unei sume s utilizând n tipuri de monede.
/* Problema monedelor
*/
#include <stdio.h>
#include <conio.h>
int st[10],a[10],b[10],n,s,nr;
void Init(int st[], int k)
{st[k]=-1;
}
int Am_Succesor(int st[], int k)
{ int s1,i,as;
if((st[k]<b[k])&&(k<=n))
{
s1=0;
for(i=1;i<=k;i++)
s1=s1+st[i]*a[i];
3
if (s1<s) as=1;
else as=0;
}
else as=0;
if (as) st[k]++;
return as;
}
int Solutie(int k)
{
int s1,i;
s1=0;
for(i=1;i<=k;i++)
s1=s1+st[i]*a[i];
if (s= =s1) return 1;
else return 0;
}
void back()
{ int k;
int As,Ev;
k=1;
Init(st,k);
while (k>0)
{ As=Am_Succesor(st,k);
if (As)
if (Solutie(k))
{
for(int i=1;i<=k;i++) printf(" %d de %d lei \t ",st[i],a[i]);
printf("\n");
nr++;
}
else {
k++;
Init(st,k);
}
else k--;
4
}
}
void main()
{
clrscr();
printf("suma="); scanf("%d",&s);
printf("nr monede="); scanf("%d",&n);
nr=0;
for (int i=1;i<=n;i++)
{ printf("valoare moneda %d= ",i);
scanf("%d",&a[i]);
b[i]=s/a[i];
}
back();
printf("nr. solutiilor=%d",nr);
getch();
}
Backtracking recursiv
5
void back(int k)
{
if (Solutie(k)) Tipar();
else
{
Init(st,k);
while (Am_Succesor(st,k))
{
if (Valid(st,k)) back(k+1);
}
}
}
6
Fiind dată o tablă de şah, de dimensiune n×
×n, se cer toate soluţiile
de aranjare a n dame astfel încât să nu se afle două dame pe
aceeaşi linie, coloană sau diagonală (damele să nu se atace
reciproc).
#include <stdio.h>
#include <conio.h>
#include <math.h>
int st[10],n;
void Tipar()
{
for(int i=1;i<=n;i++) printf("%d ",st[i]);
printf("\n");
}
void back(int k)
{ int i, j, As;
if (k= =n+1) Tipar();
else
{
for(i=st[k]+1;i<=n;i++)
{
st[k]=i;
As=1;
for(j=1; j<k; j++)
7
if (st[j]= =st[k] || abs(st[k]-st[j])= =(k-j))
As=0;
if (As) back(k+1);
}
}
st[k]=0;
}
void main()
{
printf("n="); scanf("%d",&n);
back(1);
getch();
}
8
Metoda Backtracking
Backtracking recursiv
void back(int k)
{
if (Solutie(k)) Tipar();
else
{
Init(st,k);
while (Am_Succesor(st,k))
{
if (Valid(st,k)) back(k+1);
}
}
}
1
Backtracking recursiv fără schemă
2
#include <stdio.h>
#include <conio.h>
#include <math.h>
int st[10],n;
void Tipar()
{
for(int i=1;i<=n;i++) printf("%d ",st[i]);
printf("\n");
}
void back(int k)
{ int i, j, As;
if (k= =n+1) Tipar();
else
{
for(i=st[k]+1;i<=n;i++)
{
st[k]=i;
As=1;
for(j=1; j<k; j++)
if (st[j]= =st[k] || abs(st[k]-st[j])= =(k-j))
As=0;
if (As) back(k+1);
}
}
st[k]=0;
}
void main()
{
printf("n="); scanf("%d",&n);
back(1);
getch();
}
3
Exemplul 2. Generarea recursivă a combinărilor.
Se citesc două numere naturale n şi k (k≤n). Se consideră o mulţime cu
elementele {1,2,…,n} şi se cere să se tipărească toate submulţimile sale care au k
elemente (combinări de n luate câte k).
Pe nivelul k se va afla o valoare mai mare decât pe nivelul k-1 şi mai mică sau
egală cu n-p+k.
4
/* Avem la dispozitie 6 culori: alb, galben, rosu, verde, albastru, negru.
Sa se precizeze toate drapelele tricolore care se pot proiecta, stiind ca
trebuie respectate regulile:
-Orice drapel are culoarea din mijloc galben sau verde;
-Cele trei culori din drapel sunt distincte.
*/
#include <stdio.h>
#include <conio.h>
int st[6],n,p,nr;
struct
{
char *culoare;
} cul[6];
void Init(int st[], int k)
{
st[k]=0;
}
int Am_Succesor(int st[],int k)
{
if(st[k]<n)
{
st[k]++;
return 1;
}
else return 0;
}
int Valid(int st[],int k)
{
for(int i=1;i<k;i++)
if(st[i]= =st[k]) return 0;
return 1;
}
int Solutie(int k)
{ return k= =p;}
5
void Tipar()
{
if (st[2]= =2 || st[2]= =4)
{for(int i=1;i<=p;i++) printf("%s ",cul[st[i]-1].culoare);
printf("\n"); nr++;
}
}
void back()
{ int k;
int As,Ev;
k=1;
Init(st,k);
while (k>0)
{ do { As=Am_Succesor(st,k);
if (As= =1) Ev=Valid(st,k);
} while ( (As= =1 && Ev= =0));
if (As)
if (Solutie(k)) Tipar();
else {
k++;
Init(st,k);
}
else k--;
}
}
void main()
{
clrscr();
/*printf(" 1- alb \n");
printf(" 2- galben \n");
printf(" 3- rosu \n");printf(" 4- verde \n");
printf(" 5- albastru \n");printf(" 6- negru \n");
*/
cul[0].culoare="alb";
cul[1].culoare="galben";cul[2].culoare="rosu";
6
cul[3].culoare="verde";cul[4].culoare="albastru";
cul[5].culoare="negru";
n=6; p=3; nr=0;
back();
printf("problema are %d solutii \n", nr);
getch();
}
#include <stdio.h>
#include <conio.h>
int st[10],n,b,m,nr;
7
int Am_Succesor(int st[], int k)
{
if(st[k]<n)
{ st[k]++;
return 1;
}
else return 0;
}
int Valid(int st[],int k)
{
for(int i=1;i<k;i++)
if(st[i]= =st[k]) return 0;
return 1;
}
int Solutie(int k)
{ return k= =m;}
void Tipar()
{
for(int i=1;i<=m;i++) printf("%d ",st[i]);
printf("\t"); nr++;
}
void back()
{ int k;
int As,Ev;
k=1;
st[k]=0;
while (k>0)
{ do
{ As=Am_Succesor(st,k);
if(As==1) Ev=Valid(st,k);
} while (As==1 && Ev==0);
if (As)
if (Solutie(k)) Tipar();
else {
k++;
8
Init(st,k);
}
else k--;
}
}
void main()
{
clrscr();
do
{
printf("n="); scanf("%d",&n);
printf("b="); scanf("%d",&b);
}while(n<b);
nr=0;
for(m=1;m<=b;m++)
{
back();
}
printf("\n nr. solutiilor=%d\n",nr);
getch();
}
9
10
Exemplul 4. Problema comis voiajorului.
2 3
1 4
6 5
Legăturile existente intre oraşe sunt date în matricea An,n. Elementele matricei A pot fi 0 sau 1
(matricea este binară).
Pentru rezolvarea problemei folosim o stivă st. La baza stivei (nivelul 1) se încarcă numărul 1.
Prezentăm în continuare modul de rezolvare a problemei:
11
2 de la oraşul 1 la oraşul 2 există drum, deci se va
1 urca în stivă;
2
oraşul 2 se mai găseşte în stivă, deci nu este
2
acceptat;
1
3
de la oraşul 2 la oraşul 3 există drum; prin oraşul
2
3 nu s-a mai 2 trecut, deci oraşul 3 este acceptat;
1
Algoritmul continuă în acest mod până se ajunge din nou la nivelul 1, caz în care algoritmul se
încheie.
Un succesor, între 2 şi n, aflat pe nivelul k al stivei, este considerat
valid dacă sunt îndeplinite următoarele condiţii:
• nu s-a mai trecut prin oraşul simbolizat de succesor, deci acesta
nu se regăseşte în stivă;
• există drum între oraşul aflat pe nivelul k-1 şi cel aflat pe nivelul
k,
• dacă succesorul se găseşte pe nivelul n, să existe drum de la el la
oraşul 1.
12
#include <stdio.h>
#include <conio.h>
int st[10],a[10][10],n;
void Init(int st[], int k)
{st[k]=1;
}
int Am_Succesor(int st[], int k)
{if(st[k]<n)
{
st[k]++;
return 1;
}
else return 0;
}
int Valid(int st[], int k)
{
if (a[st[k-1]][st[k]]==0) return 0;
for(int i=1;i<=k-1;i++)
if(st[i]==st[k]) return 0;
if ((k==n)&& (a[1][st[k]]==0)) return 0;
return 1;
}
int Solutie(int k)
{ return k==n;}
void Tipar()
{
for(int i=1;i<=n;i++) printf(" Nodul= %d \n ",st[i]);
printf("-------------\n");
}
void back()
{ int k;
int As,Ev;
st[1]=1;k=2;
Init(st,k);
while (k>1)
{ do {As=Am_Succesor(st,k);
if(As==1) Ev=Valid(st,k);
13
if (Solutie(k)) Tipar();
else {
k++;
Init(st,k);
}
else k--;
}
}
void main()
{
clrscr();
printf("nr noduri=");scanf("%d",&n);
for (int i=1;i<=n;i++)
for (int j=1;j<=i-1;j++)
{ printf("a[%d,%d]=",i,j);
scanf("%d",&a[i][j]);
a[j][i]=a[i][j];
}
back();
for (i=1;i<=n;i++)
printf("%d \t",st[i]);
printf("\n");
getch();
}
14
Metoda Programării Dinamice
S0 S1 S2 S3 S4 Sn-1 Sn
1
Programarea Dinamică reprezintă o metodă de rezolvare a problemelor pentru care soluţia
poate fi privită ca rezultatul a unor decizii (D1,D2,D3,...,Dn). Fiecare decizie trebuie să
satisfacă principiul optimalităţii.
b) decizia Dx depinde de deciziile D1, D2,..., Dx-1. In acest caz se aplică metoda Inapoi.
Deciziile se iau în ordinea : D1, D2,..., Dn.
k − 1 k
k + , 0 < k < n
= n − 1 n − 1
n
1, in rest
2
function C(n,k)
DACA (k=0) or (k=n) ATUNCI return 1
ALTFEL return C(n-1,k-1)+C(n-1,k)
SFDACA
3
int comb(int n, int k)
{
int i,j;
int c[20][20];
for( i=0; i<=n ;i++)
{ c[i][0]=1;
c[i][i]=1;
for( j=1;j<= i-1 ;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
}
return c[n][k];
}
4
Un algoritm de programare dinamică poate fi descris prin următoarea
succesiune de paşi:
1. se caracterizează structura unei soluţii optime;
2. se obţine recursiv valoarea unei soluţii optime;
3. se calculează de jos în sus valoarea unei soluţii optime;
5
Problema triunghiului
rezultatul va fi 17.
Rezolvare:
Se pot forma mai multe sume:
S1=2+3+6+5=16
S2=2+5+4+1=12
…………….
Sk=2+3+6+6=17 (care este şi suma maximă).
Se observă că se pot forma 2n-1 astfel de sume. A le lua în considerare
pe toate pentru a găsi valoarea optimă (maximă) nu este eficient.
6
Vom forma un triunghi, de la bază către vârf, cu sumele maxime care
se pot forma cu fiecare număr. Dacă am memorat triunghiul de numere
într-o matrice T şi calculăm sumele într-o matrice C, vom avea relaţiile
următoare:
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 se obţin astfel:
C[i,j]:=max{T[i,j]+C[i+1,j], T[i,j]+C[i+1, j+1]}, unde iœ{1,2,…,n-1}
şi jœ{1, …,i}.
Să rezolvăm problema propusă ca exemplu:
Linia 4 a matricii C va fi linia n a matricii 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.
7
#include <stdio.h>
#include <conio.h>
int n,i,j;
int t[20][20],c[20][20],drum[20][20];
void main()
{
printf("nr. linii ale triunghiului ="); scanf("%d",&n);
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
{
printf("a[%d,%d]=",i,j); scanf("%d",&t[i][j]);
}
for(j=1;j<=n;j++) c[n][j]=t[n][j];
for(i=n-1;i>=1;i--)
{
for(j=1;j<=i;j++)
if (c[i+1][j]<c[i+1][j+1])
{
c[i][j]=t[i][j]+c[i+1][j+1];
drum[i][j]=j+1;
}
else
{
c[i][j]=t[i][j]+c[i+1][j];
drum[i][j]=j;
}
}
8
i=1;
j=1;
while (i<=n)
{
printf("\t %d",t[i][j]);
j=drum[i][j];
i=i+1;
}
printf("\n");
getch();
}
9
Problema pachetelor
n = numărul de pachete
Inst = timpul de instalare a pachetului
D= timpul de descărcare a pachetului
1§ n § 100000
1§ Inst, D § 1000
10
Soluţia fiecărei subprobleme o vom reţine într-un vector min, unde
min[i]= numărul minim de secunde după care poate începe instalarea
aplicaţiei, calculat din momentul începerii descărcării pachetului i, 0 §
i< n.
Relaţia de recurenţă:
• min[n-1]=D[n-1]
(nr. minim de secunde după care poate începe instalarea pachetului
n-1, ultimul pachet, este egal cu timpul necesar descărcării complete
a pachetului n-1)
• min[i]=D[i] + max{0, min(i+1) –Inst[i]}, " 0 § i< n-1.
11
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define NMAX 1000
#define max(x,y) ((x)>(y)?(x):(y))
FILE *f; // declararea descriptorului de fisier intrare
FILE *g; // declararea descriptorului de fisier iesire
int min[NMAX], D[NMAX], Inst[NMAX];
void main()
{
if((f=fopen("c:\\borlandc\\fin.txt","r"))==0)
{
printf("Fisierul nu poate fi deschis !");
exit(1);
}
if((g=fopen("c:\\borlandc\\fout.txt","w"))==0)
{
printf("Fisierul nu poate fi creat !");
exit(1);
}
int n, i;
fscanf(f,"%d",&n);
for(i=0;i<n;i++)
fscanf(f,"%d%d",&Inst[i],&D[i]);
fclose(f);
min[n-1]=D[n-1];
for(i=n-2;i>=0;i--)
min[i]=D[i]+max(0, min[i+1]-Inst[i]);
fprintf(g, "%d\n",min[0]);
fclose(g);
getch();
}
12
Tehnici Avansate de Programare Îndrumător de laborator
Laborator 1.Pointeri în C
Problema 1. Să se scrie un program care declară o variabilă de tip “ int” și una de tip “float”, apoi să se
afișeze valorile acestora, adresele și dimensiunile lor.
Figura .1.
1
Tehnici Avansate de Programare Îndrumător de laborator
Problema 2. Să se scrie un program care realizează interschimbarea a două variabile folosind o funcție.
#include <stdio.h>
#include <conio.h>
// afisare valori noi
void interschimba(int *, int *); printf("a = %d\tb = %d", a, b);
Figura.2.
2
Tehnici Avansate de Programare Îndrumător de laborator
Problema 3. Să se scrie un program care citește și afișează elementele a două tablouri, la primul tablou
accesul se face indexat, iar la al doilea tablou, accesul se realizează prin pointeri.
Figura.3.
3
Tehnici Avansate de Programare Îndrumător de laborator
Problema 4. Se citesc și se tipăresc elementele a trei tablouri de numere întregi, de dimensiuni diferite.
Citirea elementelor unui tablou se face până la tastarea lui CTRL+Z sau până la introducerea numărului
maxim de elemente. Pentru citirea, respectiv tipărirea tablourilor se va utiliza câte o funcție care trebuie
să primească ca parametru dimensiunile tablourilor.
Figura.4.
4
Tehnici Avansate de Programare Îndrumător de laborator
Problema 5. Înlocuirea variabilelor cu indici prin expresii cu pointeri duc la optimizări, înlocuindu-se
operațiile de înmulțire care intervin în evaluarea expresiilor cu indici, prin adunări.
#include <stdio.h>
#include <conio.h> scanf_s("%f", &t[2]);
// sau scanf_s("%f", p+2);
void main()
{ printf("%.2f", t[2]);
float *p, t[10]; // sau printf("%f", *(p+2));
p = t; getch();
// sau p = &t; }
// sau p = &t[0];
Figura.5.
Problema6. Să se scrie o funcție care citește cel mult n elemente de tip double și le păstrează în zona de
memorie a cărei adresă de început este valoarea parametrului formal p a funcției.
Figura.6.
6
Tehnici Avansate de Programare Îndrumător de laborator
Problema1. Să se scrie un program pentru crearea unui fișier binar, având articole structuri cu
următoarele câmpuri:
1
Tehnici Avansate de Programare Îndrumător de laborator
printf("\n %s \t %02d/%02d/%04d \t
// afisam continutul fisierului %ld\n", a[i].nume, a[i].data.zi, a[i].data.luna,
fread(&n, sizeof(int), 1, df); a[i].data.an, a[i].suma);
fread(&citite, sizeof(aux), n, df); fclose(df);
for (i=0; i<n; i++) getch();
Figura.1.
Problema2. Să se scrie un program care copiază conținutul unui fișier al cărui nume este specificat la
linia de comandă într-un alt fișier al cărui nume este predefinit în cadrul programului.
2
Tehnici Avansate de Programare Îndrumător de laborator
La lansarea în execuție a programului pe ecran va apărea:
Figura.2.
Problema 3. Să se scrie un program care afișează lungimea celei mai lungi linii din fișierul text TEST:
/*------------------------------------------------*/
/* */
/* afiseaza lungimea lg_max a celei mai lungi */
/* linii a fisierului */
/* */
/*------------------------------------------------*/
#include <stdio.h>
while ((c=getc(f))!=EOF)
void main(void) if (c=='\n')
{ {
FILE *f; if (lg_max<lg_curenta)
char c; lg_max = lg_curenta;
int lg_max, lg_curenta; lg_curenta = 0;
}
lg_max=lg_curenta=0; else
lg_curenta++;
if (!(f=fopen("TEST", "r")))
{ fclose(f);
puts("Fisierul TEST nu poate fi deschis"); printf ("\nLinia cea mai lunga are lungimea
return; %d", lg_max);
} }
Problema 4. Să se scrie un program care copiază un fișier binar sursă în alt fișier binar destinație.
/*---------------------------------------*/
/* */
/* copiaza continutul unui fisier binar */
/* in alt fisier binar */
/* */
/----------------------------------------*/
3
Tehnici Avansate de Programare Îndrumător de laborator
#include <stdio.h> fprintf(stderr, "Fisierul dest nu poate fi
deschis\n");
void main(void) return;
{ }
FILE *fs, *fd;
char c; c=getc(fs);
while (!feof(fs))
if ((fs=fopen("sursa", "rb"))==NULL) {
{ putc(c, fd);
fprintf(stderr, "Fisierul sursa nu poate fi c=getc(fs);
deschis\n"); }
return;
} fclose(fs);
fclose(fd);
if ((fd=fopen("dest", "wb"))==NULL) }
{
Problema 5. Să se realizeze un program care păstrează evidența unei grupe de studenți. Datele despre
studenți (numele, vârsta, media) se păstrează sub forma unui fișier text. Programul trebuie să permită
următoarele opțiuni:
Se observă că cele trei operații principale efectuate asupra fișierului: adăugare, listare și modificare sunt
implementate în trei funcții distincte.
Funcția adaugă înscrie în fișier datele unui student sub forma unei înregistrări de 30 de octeți (20 pentru
nume, 1 spațiu, 2 pentru vârstă, 1 spațiu, 6 pentru medie). Acest lucru este folosit în funcția modifică, când
se repoziționează indicatorul de poziție în fișier la începutul înregistrării care urmează a fi modificată.
6
Indrumător de laborator
Problema1. Să se scrie un program care realizează sortarea unui vector prin inserție și prin
interclasare.
1
Indrumător de laborator
{ }
int *v;
int n, i; // sortare
int x[] = {30, 80, 120, 140, 170}; insertie(v, n);
int y[] = {2, 9, 11, 20}; //insertie2(v, n);
printf("Dimensiunea vectorului: "); //interclasare(x, 5, y, 4, v);
scanf("%d", &n);
v = (int *)malloc(n * sizeof(int)); // afisare vector sortat
printf("\nVector sortat:\n");
// citire vector for (i=0; i<n; i++)
for (i=0; i<n; i++) printf("%d ", v[i]);
{ free(v);
printf("v[%d] = ", i); getch();
scanf("%d", &v[i]); }
Figura.1.
2
Indrumător de laborator
Problema2. Să se scrie un program care realizează sortarea unui vector prin interschimbare.
#include <stdio.h> {
#include <malloc.h> if (v[j-1] > v[j])
#include <conio.h> {
void sort(int v[], int n) aux = v[j-1];
{ v[j-1] = v[j];
int i, ind, aux; v[j] = aux;
k = j;
do }
{ }
ind = 0; d = k;
for (i=0; i<n-1; i++) } while (s < d);
{ }
if (v[i] > v[i+1]) void main()
{ {
aux = v[i]; int *v;
v[i] = v[i+1]; int n, i;
v[i+1] = aux; printf("Dimensiunea vectorului: ");
ind = 1; scanf("%d", &n);
} v = (int *)malloc(n * sizeof(int));
}
} while (ind != 0); // citire vector
} for (i=0; i<n; i++)
{
void shaker(int v[], int n) printf("v[%d] = ", i);
{ scanf("%d", &v[i]);
int s = 0, d = n, k = n, j, aux; }
do sort(v, n);
{ //shaker(v, n);
for (j=d-1; j>s; j--)
{ // afisare vector sortat
if (v[j-1] > v[j]) printf("\nVector sortat:\n");
{ for (i=0; i<n; i++)
aux = v[j-1]; printf("%d ", v[i]);
v[j-1] = v[j];
v[j] = aux; free(v);
k = j;
} getch();
}
}
s = k;
for (j=s; j<d; j++)
3
Indrumător de laborator
Figura.2.
Problema3. Să se scrie un program care realizează sortarea unui vector prin selecție.
#include <stdio.h> }
#include <malloc.h> }
#include <conio.h>
void main()
void selectie(int v[], int n) {
{ int *v;
int i, j, aux; int n, i;
for (i=0; i<n; i++) printf("Dimensiunea vectorului: ");
{ scanf("%d", &n);
for (j=i; j<n; j++) v = (int *)malloc(n * sizeof(int));
{
if (v[i] > v[j]) // citire vector
{ for (i=0; i<n; i++)
aux = v[i]; {
v[i] = v[j]; printf("v[%d] = ", i);
v[j] = aux; scanf("%d", &v[i]);
} }
}
4
Indrumător de laborator
selectie(v, n);
free(v);
// afisare vector sortat
printf("\nVector sortat:\n"); getch();
for (i=0; i<n; i++) }
printf("%d ", v[i]);
Figura.3.
5
Indrumător de laborator
Laborator 5.Recursivitate
Problema 1. Se dă un tablou A(1,n) de numere întregi și se cere să se determine maximul elementelor sale
folosind o funcție recursivă.
Figura.1.
1
Indrumător de laborator
Problema 2. Să se scrie un program care citește pe n de tip int, calculează și afișeaza n! Folosind funcția
recursivă factorial.
Problema 3. Citirea a n cuvinte (şiruri de caractere), fiecare terminat cu spaţiu şi tipărirea lor în oglindă.
/* Programul citeste n cuvinte separate cu spatiu; (dupa ultimul cuvant va exista spatiu si <ENTER>) si
le afiseaza "in oglinda" */
Funcţia revers citeşte câte un caracter pe care îl afişează până la întâlnirea spaţiului (terminatorul
şirului de caractere). Fiecare autoapel conduce la păstrarea în stivă a variabilei locale c. Apariţia
spaţiului conduce la terminarea apelurilor recursive ale funcţiei, urmând scrierea spaţiului şi a
caracterelor în ordinea inversă introducerii lor.
2
Indrumător de laborator
{ printf("sir[%d]=",i);
if (dim_sir>=0) return scanf("%d",&sir[i]);
minim(sir[dim_sir],termen_minim(dim_sir-1)); };
else return MAXIM; printf("\nSIRUL INTRODUS\n");
} for(i=0;i<n;++i)
{
void main(void) printf("%6d",sir[i]);
{ if ((i+1) % 10 == 0) printf("\n");
int i,n; };
printf("\nIntroduceti nr de termeni ai sirului printf("\nCel mai mic termen este
n="); %d\n",termen_minim(n-1));
scanf("%d",&n); printf("\nApasati o tasta!");
printf("\nIntroduceti valorile termenilor\n"); getch();
for(i=0;i<n;++i) }
{
Problema 5. Varianta recursivă şi nerecursivă a găsirii valorii celui de al n-lea termen al şirului lui
Fibonacci.
Fib(0)=0; Fib(1)=1;
#include <stdio.h> }
#include <conio.h> }
3
Indrumător de laborator
1
Indrumător de laborator
Problema 2. Fiind date monede de valori v1, v2,...,vn şi o sumă C, să se determine numărul
minim de monede necesar pentru a acoperi suma C. Se presupune că există un număr
nelimitat de monede. (Problema monedelor)
și
să fie mai mică.
s[i]=0;
#include<stdio.h> i=1;
#include<conio.h> while((c>0)&&(i<=6))
void main() {
{ s[i]=c/a[i];
int a[6]; c=c%a[i];
a[1]=100; a[2]=50; printf("%d %d \n", s[i], c);
a[3]=20; a[4]=10; i++;
a[5]=5; a[6]=1; }
int s[6], i ,c; if (c==0)
clrscr(); for(i=1; i<=6; i++)
printf("Suma de platit="); scanf("%d", &c); printf("%d \t", s[i]);
for(i=1; i<=6; i++) else printf("nu se poate achita suma");
printf("\n");
getch();
}
2
Indrumător de laborator
Observatie:
Tehnica Greedy nu conduce pentru orice valori la Soluția optimă.
De exemplu, pentru cazul monedelor cu valorile (25,20,10,5,1) și suma C=40, tehnica Greedy
conduce la Soluția (1,0,1,1,0), care nu este Soluția optimă; varianta (0,2,0,0,0) este Soluția
optimă. Pe de altă parte există situații în care problema nu are soluții. De exemplu, pentru cazul
monedelor cu valorile (25,20,10,5) și suma C=27, problema nu are soluție.
Un exemplu de valori pentru care se poate demonstra optimitatea soluției este , multiplu al
lui pentru orice i≥2.
Problema 3. Se consideră n obiecte și un rucsac. Obiectul i are greutatea , iar rucsacul are
capacitatea M. În momentul în care se depune în rucsac o fracțiune xi, 0 <= xi <= 1 din
obiectul i profitul obținut este . Se cere să se umple rucsacul astfel încât să se obțină un cost
maxim.( Problema rucsacului ).
Problema care se pune este selectarea unei submulțimi de obiecte care să nu depășească
capacitatea rucsacului :
Aplicând tehnica Greedy, doar pentru varianta continuă putem obține o soluție optimă. În
continuare această variantă o vom analiza.
În momentul în care se depune în rucsac o fracțiune 0 ≤ ≤1 din obiectul i profitul
obținut este.
Formal problema se formulează astfel : să se determine astfel încât consumul
(1)
(2)
3
Indrumător de laborator
și
(3) 0≤ ≤1, ≥0, ≥0, 1 ≤i ≤n.
Se consideră soluție posibilă setul de valori ( ) care satisface condițiile (2) și (3).
Deci trebuie determinată acea soluție care maximizează costul (1).
De exemplu, pentru problema care are n = 3, M=20,( )=(25,24,15) și (
)=(18,15,10) există cel puțin următoarele două soluții :
( )
(1/2,1/3,1/4) 16,5 24.25
(0,0,1) 10 15
Observațiile de mai sus ne conduc la ideea încercării unei strategii care să ia în considerare
factorul de greutate cât și cel de profit. Deci, vom încerca strategia conform căreia se adaugă la
fiecare pas obiectul care are raportul maxim. Dacă obiectele sunt aranjate astfel încât :
, algoritmul corespunzător acestei strategii este :
4
Indrumător de laborator
i←1 x(i)←w(i)
WHILE(i≤n si rest <>0)DO rest←rest – w(i)
IF w(i) >rest THEN ENDIF
x(i)←rest/w(i) i←i+1
rest ←0 ENDWHILE
ELSE End
5
Indrumător de laborator
Figura.1.
Problema 4. Într-o sală, într-o zi trebuie planificate n spectacole. Pentru fiecare spectacol se
cunoaște intervalul de timp în care se desfășoară (ora de început, ora de sfârșit). Se cere să se
planifice un număr maxim de spectacole astfel încât să nu se suprapună spectacolele.
(Problema spectacolelor).
6
Indrumător de laborator
Într-o sală, într-o zi trebuie planificate n spectacole. Pentru fiecare spectacol se cunoaște
intervalul de timp în care se desfășoară (ora de început, ora de sfârșit). Se cere, să se planifice un
număr cât mai mare de spectacole astfel încât să nu se suprapună spectacolele.
Algoritmul problemei :
1. Sortarea crescătoare a spectacolelor dupa ora terminării lor;
2. Primul spectacol programat este cel care se termină cel mai devreme;
3. Alegem primul spectacol din cele ce urmează în șir după ultimul spectacol programat,
deci, acela care începe după ce s-a terminat ultimul spectacol programat;
4. Dacă nu s-a găsit un astfel de spectacol, algoritmul se încheie, asfel se programează
spectacolul găsit și algoritmul se reia de la pasul 3.
#include <stdio.h>
#include <conio.h>
int s[2][10], a[10], n, i, ora_sf; printf("- ora de inceput = ");
void sortare() scanf("%d", &s[0][i]);
{ printf("- ora de sfarsit = ");
int gata, aux; scanf("%d", &s[1][i]);
do a[i] = i;
{ }
gata = 1; sortare();
for (i=0; i<n-1; i++) ora_sf = s[1][a[0]];
{ printf("Primul spectacol este nr
if (s[1][a[i]] > s[1][a[i+1]]) %d\n", a[0]);
{ i = 1;
aux = a[i]; a[i] = a[i+1]; a[i+1] = aux; while (i<n)
gata = 0; {
} if (s[0][a[i]] >= ora_sf)
} {
} while (!gata); printf("Spectacolul urmator este nr %d\n",
} a[i]);
void main() ora_sf = s[1][a[i]];
{ }
printf("Nr. spectacole = "); i++;
scanf("%d", &n); }
for (i=0; i<n; i++) getch();
{ }
printf("Spectacolul %d\n", i);
7
Indrumător de laborator
Figura.2.
8
Indrumător de laborator
Problema 1. Se dau trei tije simbolizate prin a, b și c. Pe tija a se găsesc n discuri de diametre
diferite așejate în ordinea descrescătoare a diametrelor privite de jos în sus. Se cere să se mute
discurile de pe tija a pe tija b, folosind ca tijă auxiliară c, respectând următoarele reguli:
1. la fiecare pas se mută un singur disc;
2. nu este permis să se așeje un disc cu diametrul mai mare peste un disc cu diametrul
mai mic.( Problema turnurilor din Hanoi)
#include <stdio.h> }
#include <conio.h> else
{
int n; hanoi(n-1, a, c, b);
char a, b, c; printf("%c%c ", a, b);
void hanoi(int n, char a, char b, char c) hanoi(n-1, c, b, a);
{ }
if (n == 1) }
{
printf("%c%c ", a, b); void main()
1
Indrumător de laborator
{ c = 'c';
printf("Numarul de discuri : "); hanoi(n, a, b, c);
scanf("%d", &n); getch();
a = 'a'; }
b = 'b';
Figura.1.
2
Indrumător de laborator
scanf("%d",&n); scanf("%d",&a[i]);
} while (n>30 || n<=0); }
for(i=1; i<=n; i++) printf("cmmdc=%d\n",divimp(1,n,a));
{ getch();
printf("a[%d]=",i); }
#include<stdio.h> {
#include<conio.h> x=maxim(i,(i+j)/2);
int a[10],n; y=maxim((i+j)/2+1,j);
int maxim(int i, int j) if (x>y) return x;
{ else return y;
int x,y; }
if (i==j) return a[i]; }
else
void main ()
{
int i;
printf("nr. de elemente = ");
scanf("%d",&n);
for (i=1;i<=n;i++)
{
printf("a[%d]=",i);scanf("%d",&a[i]);
}
printf("maximul = %d\n",maxim(1,n));
getch();
}
3
Indrumător de laborator
Permutări
1 2 3
1 2 2 2 2
1 1 1 1 1 1
1 2 3
1
Indrumător de laborator
3 3 3 3 1
1 1 1 1 2 2
1 2 3 1
1 1 1 2 3 3
2 2 2 2 2 2
#include <stdio.h> {
#include <conio.h> int k = 1;
int st[10], n; int as, ev;
void init(int st[], int k) { st[k] = 0; } init(st, k);
int am_succesor(int st[], int k) while (k > 0)
{ {
if (st[k] < n) do
{ {
st[k]++; if (as =
return 1; am_succesor(st, k))
} ev = valid(st,
return 0; k);
} } while (as == 1 && ev ==
int solutie(int k) { return k==n; } 0);
int valid(int st[], int k) if (as)
{ if (solutie(k))
int i; { tiparire(); }
for (i=1; i<k; i++) else
if (st[i] == st[k]) {
return 0; k++;
init(st, k);
return 1; }
} else
void tiparire() k--;
{ }
int i; }
for (i=1; i<=n; i++)
printf("%d ", st[i]); void main()
printf("\n"); {
} printf("n = "); scanf("%d", &n);
back();
void back() getch();
2
Indrumător de laborator
Figura.1.
Problema 2. Fiind dată o tablă de șah n x n, se cer toate soluțiile de aranjare a n dame, astfel
încât să nu se afle două dame pe aceeași linie, coloană sau diagonală (damele să nu se atace
reciproc).( Problema celor n dame).
Observăm că o damă trebuie sa fie plasată singură pe linie.Plasăm prima damă pe linia 1, coloana
1.
D
3
Indrumător de laborator
D
D
Observăm că a treia damă nu poate fi plasată în linia a 3-a.Încercam atunci plasarea celei de-a
doua dame în coloana a 4-a.
D
D
D
D
D
În această situaţie dama a patra nu mai poate fi aşezată pe tabla de şah. Încercând să avansăm cu
dama a treia, observăm că nu este posibil să o plasăm nici în coloana a treia, nici în coloana a
patra, deci o vom scoate de pe tablă. Dama a doua nu mai poate avansa, deci şi ea este scoasă de
pe tablă. Avansăm cu prima damă în coloana a 2-a.
D
D
4
Indrumător de laborator
D
D
D
Acum este posibil să plasăm a patra damă în coloana a treia şi astfel am obţinut o soluţie a
problemei.
D
D
D
Algoritmul continuă în acest mod până când trebuie scoasă de pe tablă prima damă.
Pentru reprezentarea unei soluţii putem folosi un vector cu n componente (având în vedere că pe
fiecare linie se gaseşte o singură damă). De exemplu, pentru soluţia găsită avem vectorul st ce
poate fi asimilat unei stive.
Două dame se găsesc pe aceeaşi diagonală dacă şi nu mai dacă este îndeplinită condiţia:
|st(i) – st(j)|=|i-j| , (diferenţa , în modul, dintre linii şi coloane este aceeaşi).
În general, st(i)=k semnifică faptul că pe linia i dama ocupă poziţia k.
st(4) 3
st(3) 1
st(2) 4
st(1) 2
Întrucât două dame nu se pot găsi în aceeaşi coloană, rezultă că o soluţie este sub formă de
permutare. O primă idee ne conduce la generarea tuturor permutărilor şi la extragerea soluţiilor
pentru problemă. A proceda astfel, înseamnă că lucrăm conform strategiei backtracking. Aceasta
presupune ca imediat ce am găsit două dame care se atacă, să reluăm căutarea.Faţă de programul
de generare a permutărilor, programul de generare a tuturor soluţiilor problemei celor n dame are
o singură condiţie suplimentară în funcţia Valid; de aceea vom prezenta numai funcţia Valid in
continuare.
#include <stdio.h> {
#include <conio.h> st[k] = 0;
#include <math.h> }
int st[10], n; int am_succesor(int st[], int k)
void init(int st[], int k) {
5
Indrumător de laborator
6
Indrumător de laborator
Figura.2.
Problema 3. Fiind dată o hartă cu n țări, se cer toate soluțiile de colorare a hărții, utilizând cel
mult 4 culori, astfel încât două țări cu frontiera comună să fie colorate diferit.
( Problema colorării hărților).
Fiind dată o hartă cu n ţări,se cere determinarea tuturor soluţiilor de colorare a hărţii, utilizând
cel mult 4 culori , astfel încât două ţări cu frontiera comună să fie colorate diferit.
Pentru exemplificare vom considera o hartă în care ţările sunt numerotate de la 1 la 5, având
forma următoare:
7
Indrumător de laborator
8
Indrumător de laborator
Figura.3.
Problema 4 .Un comis-voiajor trebuie să viziteze un număr de n orașe. Inițial, acesta se află
într-unul dintre ele, notat cu 1. Comis-voiajorul dorește să nu treacă de două ori prin același
oraș, iar la întoarcere să revină în orașul 1. Cunoscând legăturile existente între orașe, se cere
să se tipărească toate drumurile posibile pe care le poate efectua comis-voiajorul.
9
Indrumător de laborator
În figura următoare sunt simbolizate 6 oraşe, precum şi drumurile existente între ele.
Legăturile existente între oraşe sunt date în matricea An ,n . Elementele matricei A pot fi 0 sau 1
(matricea este binară).
Pentru rezolvarea problemei folosim o stivă st. La baza stivei (nivelul 1 ) se încarcă numărul 1.
Prezentăm în ontinuare modul de rezolvare a problemei:
Algoritmul continuă în acest mod până se ajunge din nou la nivelul 1, caz în care algoritmul se
încheie.
Un succesor, între 2 şi n, aflat pe nivelul k al stivei, este considerat valid dacă sunt îndeplinite
următoarele condiţii:
• nu s-a mai trecut prin oraşul simbolizat de succesor, deci acesta nu se regăseşte în stivă;
• există drum între oraşul aflat pe nivelul k-1 şi cel aflat pe nivelul k;
• dacă succesorul se găseşte pe nivelul n, să existe drum de la el la oraşul 1.
Figura.4.
12
Indrumător de laborator
Problema 1. Se citesc n și p numere naturale, n mai mare sau egal cu p. Se cere să se genereze
toate aranjamentele de n luate câte p.(Generarea recursivă a aranjamentelor)
Aranjamente
, sau
1
Indrumător de laborator
Figura.1.
Combinări
, sau
2
Indrumător de laborator
Pentru k=1, trebuie să se tipărească toate submulțimile cu un singur element. Acestea sunt:
{1}, {2}…,{n}. Întrucât elementele unei submulțimi sunt distincte, le vom reține într-un singur
vector în ordine crescătoare.
Presupunem că am generat o submulțime cu p elemente (p<=k) a mulțimii A. Aceasta este
{i1,i2,…,ip}, i1<i2<…ip. Utilizând această submulțime cu p+1 elemente ale mulțimii A
(componenta (p+1) va lua valorile de la ( p+1) pana la n, pentru că, pentru a evita repetiția, o
soluție conține numere strict crescătoare):
• {i1,i2,…,ip,ip+1};
• {i1,i2,…,ip,ip+2};
• {…………………….};
• {i1,i2,…,ip,in}.
Pe nivelul k se va află o valoare mai mare decât pe nivelul ( k-1) și mai mică sau egală cu ( n-
p+k).
3
Indrumător de laborator
Figura.2.
Problema 3. Fiind dată o tablă de șah, de dimensiune n*n, se cer ca toate soluțiile de aranjare
a n dame astfel încât să nu se afle două dame pe aceeași linie, coloană sau diagonal (damele
să nu se atace reciproc).
Mecanismul de rezolvare este același ca în cazul standardizat (o soluție se reține într-un vector
numit t). Pentru o anumită componentă a vectorului se caută un succesor de la valoarea care se
găsește la un element dat până la valoarea maximă posibilă(n). În cazul în care se găsește un
succesor, se verifică dacă este valid, caz în care se apelează procedura pentru valoarea
următoare, astfel, se caută următorul succesor. În cazul în care acesta nu există se revine la
nivelul anterior. Initializarea se face la început (pentru tot vectorul) și la revenire. Tipărirea
soluției se realizează în momentul atingerii nivelului n+1.
#include<stdio.h> else
#include<conio.h> {
#include<math.h> for(i=st[k]+1;i<=n;i++)
{
void Tipar st[k]=i;
{ As=1;
for(int i=1;i<=n;i++) for(j=1;j<k;j++)
printf(“%d”,st[i]); if(st[j]==st[k]||abs(st[k])-
printf(“\n”); st[j]==(k-j))
} As=0;
void back(int k) if(As) back(k+1);
{ }
Int I,j,As; }
if(k==n+1) Tipar(); st[k]=0;
4
Indrumător de laborator
}
void main()
{
printf(“n=”);
scanf(“%d”,&n);
back(1);
getch();
}
5
Tehnici Avansate de Programare Îndrumător de laborator
Problema 1.
Se consideră un triunghi de numere. Să se calculeze cea mai mare sumă a numerelor ce apar pe
drumurile ce pleacă din vârf și ajung la bază astfel:
- în fiecare drum succesorul unui număr se află pe rândul de mai jos,sub sau pe diagonală
la dreapta.
Se cere, de asemenea, să se determine care sunt numerele ce alcătuiesc suma maximă
determinată. ( Problema triunghiului ).
Exemplu:
Pentru triunghiul
3 5
6 3 4
5 6 1 4
Rezultatul va fi 17.
Rezolvare:
Se pot forma mai multe sume:
S1=2+3+6+5=16
S2=2+5+4+1=12
……………………….
Se observă că se pot forma 2 n − 1 astfel de sume. A le lua în considerare pe toate pentru a găsi
valoarea optimă (maximă) nu este eficient.
Fie un șir de n numere (care respectă condițiile problemei și care formează suma maximă). În
acest șir considerăm numărul 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 începând cu numărul preluat de pe linia i.
1
Tehnici Avansate de Programare Îndrumător de laborator
Vom forma un triunghi, de la bază la vârf, cu sumele maxime care se pot forma cu fiecare
număr. Dacă memorăm triunghiul de numere într-o matrice T și calculăm sumele într-o matrice
C, vom avea relațiile următoare:
C[n,1]:=T[n,1];
C[n,2]:=T[n,2];
…………………
C[n,n]:=T[n,n];
5 6 1 4;
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.
#include <stdio.h>
#include <conio.h>
2
Tehnici Avansate de Programare Îndrumător de laborator
{
int a[20][20], t[20][20], c[20][20], drum[20] c[i][j] = t[i][j] + c[i+1][j+1];
[20], n, i, j; drum[i][j] = j + 1;
}
void main() else
{ {
printf("Nrumarul de linii ale triunghiului = c[i][j] = t[i][j] + c[i+1][j];
"); scanf("%d", &n);
for (i=1; i<=n; i++) drum[i][j] = j;
for (j=1; j<=i; j++) }
{ }
printf("a[%d][%d] = ", i, j); scanf("%d", }
&t[i][j]); printf("Suma maxima este = %d\n",
} c[1][1]);
for (j=1; j<=n; j++) i = j = 1;
c[n][j] = t[n][j]; while (i <= n)
for (i=n-1; i>=1; i--) {
{ printf("\t%d", t[i][j]);
for (j=1; j<=i; j++) j = drum[i][j];
{ i++;
if (c[i+1][j] < c[i+1][j+1]) }
printf("\n");
getch();
}
Figura.1.
3
Tehnici Avansate de Programare Îndrumător de laborator
Problema 2.
Presupunem că avem de înmulțit două matrici : An , p cu B p ,m . În mod evident, rezultatul va fi o
matrice C n ,m . Se pune problema de a afla câte înmulțiri au fost făcute pentru a obține
matricea C. Prin înmulțirea liniei 1 cu coloana 1 se fac p înmulțiri, întrucât au p elemente.
Dar linia 1 se înmulțește cu toate cele m coloane, deci se fac m*p înmulțirii. În mod analog se
procedează pentru toate cele n linii ale matricii A, deci se fac n*p*m înmulțiri. Reținem acest
rezultat.( Inmultirea optima a unui sir de matrici )
Pentru rezolvare se ține cont de următoarele relații existente între componentele matricii A:
• A(i,j)=0;
• A(i,i+1)=DIM(i)*DIM (i+1)*DIM(i+2);
• A(i,j)=min{A(i,k)+A(k+1,j)+DIM(k+1)*DIM(j+1)}
4
Tehnici Avansate de Programare Îndrumător de laborator
Relația sintetizează faptul că pentru a obține numărul de înmulțiri optim pentru produsul
Ai ∗ Ai + 1 * ....... A j . , se înmulțesc două matrici, una obținută ca produs optim între
Ai ∗ Ai + 1 * ....... A j . și cealaltă obținută ca produs optim între Ak + 1 * Ak + 2 ∗ ......... * A j , în ipoteza în
care cunoaștem numărul de înmulțiri necesar efectuării acestor două produse, oricare ar fi k,
cuprins între limitele date.
Această observație este o consecință direct a programării dinamice și anume că produsul efectuat
optim între matricile prezentate se reduce în ultimă instanță la a efectua un produs între două
matrici cu condiția ca acestea să fie calculate optim ( produsul lor să aibă un număr minim de
înmulțiri).
#include <stdio.h> j = i + k;
#include <conio.h> a[i][j] = maxint;
#define maxint 32565
for (l=i; l<=j-1; l++)
long a[10][10]; {
int dim[10], i, n; m = a[i][l] + a[l+1][j] + dim[i] * dim[l+1] *
void costopt(int n, int dim[], long a[][10]) dim[j+1];
{
int k, i, j, l;
long m; if (a[i][j] > m)
{
for (i=1; i<=n; i++) a[i][j] = m;
a[i][i] = 0; a[j][i] = l;
}
for (k=1; k<=n-1; k++) }
for (i=1; i<=n; i++) }
{ printf("cost optim = %ld\n", a[1][n]);
5
Tehnici Avansate de Programare Îndrumător de laborator
Figura .2.
Problema 3.
Un student descarcă de pe Internet o aplicație. Aplicația a fost împărțită în mai multe pachete,
iar pachetele trebuie descărcate într-o ordine fixată.Se cunoaște timpul de descărcare pentru
fiecare pachet, precum și timpul necesare instalării fiecărui pachet.
Studentul vrea să testeze aplicația cât mai repede și vrea să înceapă instalarea înainte de a se
fi terminat descărcarea tuturor pachetelor. Se știe că odată ce începe instalarea nu mai poate
fi întreruptă(va da eroare la momentul în care este necesară instalarea unui pachet acesta nu
este complet descărcat).( Problema pachetelor ) .
6
Tehnici Avansate de Programare Îndrumător de laborator