Sunteți pe pagina 1din 12

Metoda Greedy

1.Problema restului de plata

Avand la dispozitie o multime de bancnote, cum poate fi achitat un rest de plata


folosind un numar minim de bancnote.

Sa notam cu R restul care trebuie achitat si cu M={m1,,mn} multimea bancnotelor pe


care le avem la dispozitie. Evident ca M {1,5,10,50,100,200,500} si presupunem ca
fiecare bancnota mi M exista intr-un numar suficient de mare. Avem:
R

nimi , 0 ni R

Elementele problemei sunt urmatoarele:

Multimea M={m1, . . . ,mn} a bancnotelor pe care le avem la dispozitie;


O solutie acceptabila este o submultime de bancnote Sj={mi1, . . .,mip} astfel incat
Rj=
nikmik R; fie sj=
nik ;
O solutie posibila este o solutie acceptabila Sj astfel incat Rj=R, fie P={S1, . . .,Sq}
multimea solutiilor posibile;
O solutie optima este o solutie posibila Sp astfel incat sp=min{s1, . . .,sq}, unde si
corespunde la Si din P, i=1, . . .,q;
Criteriul de selectie al bancnotelor din multimea M este evident mj=max{m1, . . .,mn},
o Mj n-a fost inca selectata. Adica, se selecteaza bancnota care are valoarea cea
mai mare.
Codul sursa al programului este:
#include<stdio.h>
#include<stdlib.h>
void ordonare (int* b, int n)
{
int sortat, aux, i;
do
{
sortat=1;
for (i=0;i n-1;i++)
if (b[i] b[i+1])
{
aux=b[i];
b[i]=b[i+1];
b[i+1]=aux;

sortat=0;
}
}
while (!sortat);
}
void afisare(int* sol, int* b, int n)
{
int i;
for (i=0;i n;i++)
if (sol[i]
)
printf(%d bancnote de %d lei\n, sol[i], b[i]);
}
void main( )
{
int n, s, I, *sol, *b;
printf (Numarul de tipuri de bancnote:);
scanf (%d,&n);
b=(int*)malloc(n*sizeof(int));
sol=(int*)malloc(n*sizeof(int));
for (i=0;i
;i++)
{
printf (tip[%d]=, i);
scanf (%d, &b[i]);
}
printf (Suma care trebuie platita:);
scanf (%d, &s);
ordonare (b,n);
for (i=0; i n;i++)
{
sol[i]=s/b[i];
s-=sol[i]*b[i];
}
if (s>o)
printf (Suma nu s-a putut plati!!!);
else
afisare (sol, b, n);
free (b);
free(sol);
}

2.Problema submultimii cu valoare maxima

Se da o multime M={m1, . . . ,mn} cu elemente numere reale. Sa se determine o


submultime a sa, S={mi1, . . ,mip} astfel incat
mik sa fie maxima.
Rezolvare
Daca mi
oricare ar fi miM atunci S={max{m1, . . .,mip}}. Daca exista mi
miM,
atunci rezolvam problema cu metoda Greedy. In acest caz elementele problemei
sunt urmatoarele:
Multimea M={m1, . . . ,mn} a elementelor de numere reale date;
O solutie acceptabila este o submultime S={mi1, . . . ,mip} cu proprietatea ca
mik
k=1, . . . ,p;
O solutie posibila este o solutie acceptabila S care contine toate elementele mi
din M cu mi
O solutie optima este o solutie posibila; vom determina solutia optima cu
toate elementele mi>0;
Criteriul de selectie este evident mi>0;
Codul sursa al programului este:
#include<stdio.h>
#include<limits.h>
void main()
{
int n, a[20], s[20], i, k, max;
printf("n=");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf("a[%d]=",i);
scanf("%d",&a[i]);
}

max=-INT_MAX;
k=0;
for(i=1;i<=n;i++)
if (a[i]>0)
s[++k]=a[i];
else
if(a[i]>max)
max=a[i];
if(k==0)
s[++k]=max;
printf("Elementele care formeaza suma maxima:");
for(i=1;i<=k;i++)
printf("%d",s[i]);
printf("\n");

Metoda Divide et Impera


1.Sa se determine cel mai mic element dintr-un sir de numere reale A={a1, . . . ,an).
Aplicam metoda Divide et Impera. In acest caz, m=[(p+q)/2] si consideram problema
rezolvabila direct, daca numarul de elemente din secventa este cel mult 2, deci q-p
Codul sursa al programului este:
#include<stdio.h>
int min(int x, int y)

{
return x<=y ? x:y;
}
int minim(int a[20], int p, int q)
{
int m;
if (q-p<=1)//daca sirul are 1 sau 2 elemente
return min(a[p],a[q]);
m=(p+q)/2;
return min(minim(a,p,m),minim(a,m+1,q));
}
void main()
{
int n,i,a[20];
printf("n=");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf("a[%d]=",i);
scanf("%d",&a[i]);
}
printf("Minimul din sir este: %d\n",minim(a, 1, n));
}

2. Problema de calcul a puterii unui numar


Sa se scrie o functie care calculeaza valoarea lui an folosind cat mai putine operatii, unde a
este un numar real iar n este un numar natural strict pozitiv.
Ideea de rezolvare a acestei problem are la baza faptul ca se poate calcula valoarea lui a n in
functie de valoarea lui an/2 astfel:

a, daca n=1

an=

(an/2)2, daca n este par

(an/2)2 *a, daca n este impar

Codul sursa al programului este:


#include<stdio.h>
double putere(double a, int n)
{
if(n==1)
return a;
else
{
double x=putere(a,n/2);
if(n%2==0)
return x*x;
else
return x*x*a;

}
}
void main()
{
double a;
int n;
printf("a=");
scanf("%1f",&a);
printf("n=");
scanf("%d",&n);
printf("Calculul puterii:%10.21f\n",putere(a,n));

Metoda Backtracking
1.Colorarea hartilor
Fiind data o harta cu n tari, se cere sa se genereze toate solutiile de colorare a hartii cu m
culori astfel incat pentru fiecare tara sa se foloseasca o singura culoare si doua tari
vecine(cu frontier comuna) sa fie colorate diferit.
Configuratia hartii este furnizata cu ajutorul unei matrice H=(hij)nn
1, daca tara I este vecina cu tara j
hij=
0, in caz contrar

Fie C={c1, . . . ,cm}={1, . . . ,m} multimea celor m culori si T={1, . . . ,n} multimea celor n tari.
Elementele problemei sunt urmatoarele:

Sk=C, k=1, . . . ,n
O solutie posibila este de forma s=(s1, . . . ,sn), skC, k=1, . . .,n;
Restrictiile interne sunt: si sj daca hij=1, i=1, . . . ,n, j=1, . . . ,n;
Conditiile de continuare sunt: si sk pentru orice tara I din {1, . . . ,k-1 }T, vecina cu
tara k.

Codul sursa al programului este:


#include <stdio.h>
void afisare(int s[20], int n)
{
int i;
for(i=1;i<=n;i++)
printf("Tara %d are culoarea %d\n",i,s[i]);
printf("\n");
}
int cont(int s[20], int k, int h[20][20]);
{
int i;
for(i=1;i<k;i++)
if(h[i][k]==1 && s[i]==s[k])
return 0;
return 1;
}
void back(int n, int m, int h[20][20])
{
int k,s[20];

k=1;
s[1]=0;
while(k>0)
{
while(s[k]<m)
{
s[k]++;
if(cont(s,k,h))
if(k==n)
afisare(s,n);
else s[++k]=0;
}
k--;
}
}
void main()
{
int n, m, h[20][20], i, j;
printf("Numarul de tari:");
scanf("%d",&n);
printf("Numarul de culori:");
scanf("%d",&m);
//citire matrice de adiacenta a tarilor
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)

if(i!=j)
{
printf("h[&d][&d]=", i, j)
scanf("&d",&h[i][j]);
}
back(n,m,h);
}

2. Problema permutarilor
Sa se afiseze toate permutarile de cate n elemente. De exemplu, pentru n=3 acestea sunt
1,2,3; 1,3,2; 2,1,3; 2,3,1; 3,1,2; 3,2,1.
Codul sursa al programului este:
#include <stdio.h>
void afisare(int s[20], int n)
{
int i;
for(i=1;i<=n;i++)
printf("%d",s[i]);
printf("\n");
}
int cont(int s[20], int k)
{
int i;
for(i=1;i<k;i++)
if(s[i]==s[k])
return 0;

return 1;
}
void back(int n)
{
int k, s[20];
k=1;
s[1]=0;
while(K>0)
{
while(s[k]<n);
{
s[k]++;
if(cont(s,k))
if(k==n)
afisare(s,n);
else
s[++k]=0;
}
k--;
}
}
void main()
{
int n;
printf("N=");

scanf("%d",&n);
back n;
}