Sunteți pe pagina 1din 10

Aplicații ale metodei Greedy

Probleme propuse:
1. Problema rucsacului, varianta continuă. Să se scrie subprogramul C pentru rezolvarea
problemei rucsacului. Se consideră un mijloc de transport cu o capacitate dată ( C ). Cu
acesta trebuie transportate obiecte dintr-o mulțime A={ ai ∨i=1 ,n }. Fiecare obiect ocupă o
capacitate specifică c i și aduce un câștig specific vi – fiecare obiect luat separat încape în
mijlocul de transport. Se cere să se determine o modalitate de încărcare care să
maximizeze cîștigul obținut la un transport. Obiectele transportate pot fi fractionate. În
acest caz se va utiliza întotdeauna întreaga capacitate de transport.

2. Problema rucsacului, varianta întreagă. Să se scrie subprogramul C pentru rezolvarea


problemei rucsacului. Se consideră un mijloc de transport cu o capacitate dată ( C ). Cu
acesta trebuie transportate obiecte dintr-o mulțime A={ ai ∨i=1 ,n }. Fiecare obiect ocupă o
capacitate specifică c i și aduce un câștig specific vi – fiecare obiect luat separat încape în
mijlocul de transport. Se cere să se determine o modalitate de încărcare care să
maximizeze cîștigul obținut la un transport. Obiectele transportate nu pot fi fractionate.

3. Se dă o mulțime de elemente reale A={ a1 , a2 , … , an , }. Se cere să se scrie subprogramul care


determină o submulțime S ⊆ A astfel încât suma elementelor submulțimii S să fie cea mai
mare posibilă (problema sumei maxime).

4. Să se scrie subprogramul C care permite plata unei sume S ∈ N folosind cât mai puține
bancnote din tipurile (valorile) a i , i=1 , n, știind că printre acestea se află și bancnota cu
valoare unitate. Sunt disponibile cantități nelimitate din fiecare tip de bancnotă.
Probleme rezolvate

1. Problema rucsacului - Să se scrie subprogramul C pentru rezolvarea problemei rucsacului.


Se consideră un mijloc de transport cu o capacitate dată (C ). Cu acesta trebuie transportate
obiecte dintr-o mulțime A={ ai ∨i=1 ,n }. Fiecare obiect ocupă o capacitate specifică c i și aduce
un câștig specific vi – fiecare obiect luat separat încape în mijlocul de transport. Se cere să se
determine o modalitate de încărcare care să maximizeze câștigul obținut la un transport.
Dacă obiectele transportate pot fi fracționate, problema este numită continuă. În acest caz se
va utiliza întotdeauna întreaga capacitate de transport.

Cea mai bună soluție se obține dacă se folosește o valoare derivată: câștigul unitar (c i /v i ). La fiecare pas se
ia în considerare următorul element al mulțimii sortate descrescător (alegere). Dacă acesta încape în
mijlocul de transport (verificare), e adăugat la soluție (adăugare) și se diminuează capacitatea de transport
rămasă disponibilă. Dacă nu încape, atunci, dacă problema este continuă, se ia din obiectul curent atât cât
încape (adăugare). Restul obiectelor se resping și algoritmul se termină.

Pentru reprezentarea soluției se poate folosi un vector în care fiecare element are valoarea 1 (obiect
acceptat) sau 0 (obiect respins). În cazul în care se acceptă fracționarea obiectelor, unul singur va fi
fracționat, iar elementul din vectorul soluție corespunzător lui va avea o valoare în intervalul ( 0,1 ) .

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<conio.h>

//problema rucsacului, continua


// I: capacitate totala (q), nr. obiecte (n), capacitate ocupata (c), castig (v)
// E: solutia x (x[i]= raportul in care e incarcat obiectul i)
//.....................................
//...............................................

void main()
{ //exemplu de apel
float CT; //capacitate totala de transport
float c[30]; //capacitati
float v[30]; //venituri
float sol[30], a, castig;
int i, j,n;
printf("Introduceti capacitatea totala a rucsacului:"); scanf("%f", &CT);
printf("Introduceti numarul de obiecte:"); scanf("%d", &n);
for (i = 0; i < n; i++)
{
printf("Capacitatea obietului %d: ", i + 1); scanf("%f", &c[i]);
printf("Venitul obietului %d: ", i + 1); scanf("%f", &v[i]);
}

//prelucrare preliminara
//sortarea obiectelor
for (i = 0; i < n - 1; i++)
for (j = i + 1; j < n; j++)
if (v[i] / c[i] < v[j] / c[j]) //castig unitar
{
a = v[i]; v[i] = v[j]; v[j] = a;
a = c[i]; c[i] = c[j]; c[j] = a;
}

//apel functie
//..................

//afisare rezultate
//........................

2. Problema rucsacului, varianta întreagă


Dacă obiectele nu pot fi fracționate, problema este numită întreagă. În acest caz e posibil ca
soluția obținută să nu utilizeze întreaga capacitate de transport. De asemenea, soluția
obținută poate să nu fie optimă. În plus, este posibil să existe o soluție de utilizare a întregii
capacități de transport, dar aceasta să nu fie găsită prin algoritmul de tip Greedy.
Cea mai bună soluție se obține dacă se folosește o valoare derivată: câștigul unitar (c i /v i ). La fiecare pas se
ia în considerare următorul element al mulțimii sortate descrescător (alegere). Dacă acesta încape în
mijlocul de transport (verificare), este adăugat la soluție (adăugare) și se diminuează capacitatea de
transport rămasă disponibilă. Dacă nu încape, atunci, dacă problema este întreagă, se respinge obiectul
curent.

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<conio.h>
//problema rucsacului, intreaga
// I: capacitate totala (q), nr. obiecte (n), capacitate ocupata (c), castig (v)
// E: solutia x (x[i]= 0-obiectul i nu e incarcat, 1-obiectul i e incarcat)
//...............................

void main()
{ //exemplu de apel
float CT; //capacitate totala de transport
float c[30]; //capacitati
float v[30], a, castig; //venituri
int sol[30];
int i, j,n;
printf("Introduceti capacitatea totala a rucsacului:"); scanf("%f", &CT);
printf("Introduceti numarul de obiecte:"); scanf("%d", &n);
for (i = 0; i < n; i++)
{
printf("Capacitatea obietului %d: ", i + 1); scanf("%f", &c[i]);
printf("Venitul obietului %d: ", i + 1); scanf("%f", &v[i]);
}

//prelucrare preliminara
//sortarea obiectelor
for (i = 0; i < n - 1; i++)
for (j = i + 1; j < n; j++)
if (v[i] / c[i] < v[j] / c[j]) //castig unitar
{
a = v[i]; v[i] = v[j]; v[j] = a;
a = c[i]; c[i] = c[j]; c[j] = a;
}

//apel functie
//.....................

//afisare rezultate
//...................

}
3. Problema sumei maxime

Se dă o mulțime de elemente reale A={ a1 , a2 , … , an , }. Se cere să se scrie subprogramul care


determină o submulțime S ⊆ A astfel încât suma elementelor submulțimii S să fie cea mai mare
posibilă (problema sumei maxime).
O sortare inițială descrescătoare a mulțimii date asigură un număr mai mic de pași la aplicarea algoritmului
Greedy (oprire la primul element nul/negativ), dar crește complexitatea la nivel general, de aceea e
preferabil (în acest caz) să nu se facă prelucrarea inițială și să se analizeze toate elementele mulțimii
inițiale. Subprogramul următor rezolvă problema sumei maxime, fără sortare prealabilă a mulțimii inițiale,
fiind astfel necesară parcurgerea întregii mulțimi.

Obs: Ce se întâmplă dacă toate elementele din vector sunt negative? Cum se va proceda în acest caz la
rezolvarea problemei?

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<conio.h>

// Submultimea care da suma maxima: se iau doar elementele (strict) pozitive

// I: multimea (a), numar de elemente (n)

// E: submultimea (b), numar de elemente (nr)

//...........

void main()

float a[100], b[100];

int n, i, nr;

printf("n="); scanf("%d", &n);

for(i=0;i<n;i++)

{printf("a[%d]=",i); scanf("%f", &a[i]);}

//.......................

}
4. Plata unei sume cu bacnota unitate
Să se scrie subprogramul C care permite plata unei sume S ∈ N folosind cât mai puține
bancnote din tipurile (valorile) a i , i=1 , n, știind că printre acestea se află și bancnota cu
valoare unitate. Sunt disponibile cantități nelimitate din fiecare tip de bancnotă.
Pentru a folosi cât mai puține bancnote, trebuie utilizate bancnote cu valori cât mai mare, ceea ce duce la
sortarea mulțimii date în ordine descrescătoare. Astfel, bancnotele cu valorile cele mai mari vor fi primele
luate în considerare. Soluția poate fi reprezentată ca un vector B= { bi ∈ N∨i=1 , n } , în care fiecare
element b i arată câte bancnote de tipul a i trebuie utilizate.

Pornind de la valoarea inițială S, se acoperă cât se poate de mult cu cel mai mare tip de bancnotă, apoi se
ajustează suma rămasă de plată. Se continuă cu fiecare tip de bancnotă, până când suma rămasă este zero.
Dacă mai rămân tipuri de bancnote neinvestigate, ele rămân nefolosite. Parametrul t este un vector cu
tipurile de bancnote, aranjate în ordinea descrescătoare a valorii nominale.

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<conio.h>

// Plata unei sume, cu bancnota unitate, cu numar minim de bancnote

// I: suma (s), tipuri bancnote (t), numar tipuri (n)

// E: nr. din fiecare tip

//.................................

void sortare (int x[], int n)

int i,j, aux;

for (i=0;i<n-1;i++)

for(j=i+1;j<n;j++)

if(x[i]<x[j])

aux=x[i];x[i]=x[j];x[j]=aux;

}
}

void main()

int t[100], sol[100], s,n,i;

printf("n="); scanf("%d", &n);

for(i=0;i<n;i++)

{printf("t[%d]=",i); scanf("%d", &t[i]);}

printf("Suma de plata:"); scanf("%d", &s);

sortare(t,n); // se sorteaza vectorul cu tipurile de bacnote in ordine descrescatoare a valorilor

//..........................

Daca vectorul initial nu este sortat, el va fi sortat inainte de apelarea subprogramului

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