Sunteți pe pagina 1din 15

Capitolul 2.

Tehnici de programare.
Tema. Metoda trierii.
Aranjamente și
combinari
Definiție
Fie P o problemă, soluţia căreia poate fi găsită analizând
consecutiv toate elementele si ale unei mulţimii finite
S={s1, s2 , s3 , ... , sn} denumită mulţimea soluţiilor posibile.
În cele mai simple cazuri elementele si (1≤ i ≤ n) pot fi
reprezentate prin valori de tipuri simple: numerice, char, boolean.
În problemele mai complicate suntem nevoiţi să reprezentăm
aceste elemente prin tablouri sau articole.
Se menţionează că în majoritatea problemelor soluţiile posibile
s1, s2, s3, ... ,sn nu sunt indicate explicit în enunţul problemei şi
elaborarea algoritmilor pentru calcularea lor cade în sarcina
programatorului.
Schema generală a unui algoritm bazat pe
metoda trierii
sau poate fi redată cu
ajutorul unui ciclu:

unde SolutiePosibila este o expresie


booleană care returnează valoarea true
(1) dacă elementul sii satisface condiţiile
problemei şi false (0) în caz contrar, iar
PrelucrareaSolutiei este un
subprogram care efectuează prelucrarea
elementului selectat. De obicei,
prelucrarea lui sii constă în afişarea la
ecran.
Exemplu 1
 Se consideră numerele naturale din mulţimea {0, 1, 2,…, n }.
Scrieţi un program care determină numărul K de elemente din această
mulţime, pentru care suma cifrelor lor este egală cu m.
 Rezolvare.

Evident, mulţimea soluţiilor posibile S={0, 1, 2,…, n }.


În programul ce urmează suma cifrelor oricărui număr natural i din
mulţimea S se calculează cu ajutorul funcţiei SumaCifrelor.
Decuparea cifrelor zecimale din reprezentarea numărului natural i se
efectuează de la dreapta la stânga prin operaţiile de împărţire întreagă
a numărului i şi a câturilor respective la baza 10.

Din analiza programului prezentat rezultă că complexitatea


temporală a algoritmului respectiv este O(n).
//Rezolvarea exemplului_1
#include <iostream>
using namespace std;
int
int i,
i, K,
K, m,
m, n;
n; //Declarare
//Declarare variabile
variabile globale
globale
//
// Funcţia
Funcţia de
de determinare
determinare a
a sumei
sumei cifrelor
cifrelor numărului
numărului natural
natural i
i
int SumaCifrelor(int i)
{
{ int
int suma;
suma;
suma=0;
do
{ suma=suma + (i%10); // // Adunarea
Adunarea cifrei
cifrei decupate
decupate la
la sumă
sumă
i= i/10; } //Eliminarea
//Eliminarea ultimei
ultimei cifre
cifre din
din numărul
numărul ii
while (i>0); return suma;
}
 int main()
{ cout<<"Dati n:"; cin>>n;
cout<<"Dati m:"; cin>>m;
K=0;
for( i=0; i<=n; i++)
{ if (SumaCifrelor(i)==m)
{cout<<"i="<<i<<" "; K++;}
}
cout<<endl<<"K="<<K;
cout<<endl<<"K="<<K; return
return 0; 0;
}
Exemplu 2
Să se scrie un program care determină toate secvenţele binare de
lungime n, fiecare din ele conţinând nu mai puţin de k cifre de 1.
Intrare: numerele naturale n (1< n < 20) şi k (k<n) se citesc de

la tastatură.
Ieşire: fiecare linie a fişierului text secv.out va conţine câte o

secvenţă binară distinctă, ce corespunde condiţiilor din enunţul


problemei.
Rezolvare. Numărul secvenţelor binare de lungime n este 2n, finit.

Prin urmare, pentru problema dată poate fi aplicată metoda trierii.


Modelul matematic

Complexitatea temporală a algoritmului aplicat la rezolvarea


exemplului al doilea este O(2nn).
//Exemplu_Triere_2 void urmator( )
#include<iostream> // Generarea
secventei urmatoare
using namespace std; { int j;
#include <fstream> j=n;
#define nmax 20 while (b[j]==1)
ofstream g("secv.out"); {b[j]=0; j--;}
int b[nmax]; b[j]=1;
int r, i, n, k; }
   
int numara() int main()
// Numararea cifrelor de
1 din secvenţa curenta { cout<<"n="; cin>>n;
{ int s, j; cout<<"k="; cin>>k;
s=0; for (i=1;i<=n;i++)b[i]=0;
for (j=1; j<=n; j++) do
s=s+b[j]; { r=numara();
return s; } if(r>=k) scrie();
  if (r<n)
void scrie() urmator();
// Îscrirea }
secventei curente B in fisierul de while(r<n);
iesire g.close();
{ int j; return 0;
for (j=1; j<=n; j++) }
g<<b[j]<<" ";
g<<endl; }
 
Metoda trierii este aplicată numai în scopuri
didactice sau pentu elaborarea unor programe
al cărora timp de execuţie nu este critic.
Generarea combinărilor
O modalitate de a alege m obiecte din n obiecte date, fără a conta ordinea,
se numeşte combinare.
Fie mulţimea C={c1, c2, … , cn}. Toate modalităţile de a selecta m elemente
distincte din cele n elemente ale mulţimii C poartă numele de combinări de n
elemente luate câte m. Numărul de combinări se calculează după formula:

De exemplu, pentru I={1, 2, 3, 4, 5} şi m = 3 avem:


iar toate combinările respective, scrise în ordine lexicografică sunt: [1,2,3],
[1,2,4], [1,2,5], [1,3,4], [1,3,5], [1,4,5], [2,3,4], [2,3,5], [2,4,5], [3,4,5].
Algoritmul de generare a combinărilor în ordine lexicografică se poate descrie
astfel: Alegem cele mai mici m (3) numere din cele n (5) avute (în cazul nostru
123) –acestea vor constitui combinarea iniţială [1,2,3]. Evident, că ultima, din
şirul ordonat lexicografic va fi combinarea Cn = [3,4,5].
Se poate demonstra că timpul cerut de un algoritm bazat pe
generarea tuturor combinărilor este de ordinul O(n k ), unde k =
min(m, n – m + 1), deci polinomial.
Program generare Combinari
// Generare combinari Indicator=false;
#include<iostream> unu:cout<<endl; }
using namespace std;
#define mmax 20;
int C[mmax];
int i, n, m; bool Indicator;
int main()
void GenComb (bool &Indicator) { cout<<"Dati n:"; cin>>n;
{ int i,j; cout<<"Dati m:"; cin>>m;
//combinarea initiala Indicator=false;
if (not Indicator) do
{ for (i=1; i<=m; i++) C[i]=i; { GenComb(Indicator);
Indicator=true; if (Indicator)
goto unu; } { for(i=1;i<=m; i++)
// Succesorul combinarii curente cout<<C[i]<<" ";}
for (i=m; i>=1; i— cout<<endl;
if (C[i]<(n-m+i)){ C[i]=C[i]+1; }
while (Indicator);
for (j=i+1; j<=m; j++) return 0;
Generarea aranjamente
Problemă: Fie mulţimea A={a1, a2,…, an} şi 0 < m ≤ n. Să se genereze toate
modalităţile de selecţie şi aranjare a m elemente distincte din mulţimea A.
Soluţiile acestei probleme se numesc aranjamente de n elemente luate câte m
şi numărul lor este dat de formula :

Exemplu: Pentru A={1,2,3} şi m = 2 aranjamentele sunt: (1,2),


(2,1), (1,3), (3,1), (2,3), (3,2).
Problema generării aranjamentelor unei mulţimi A cu n elemente poate fi redusă la
generarea aranjamentelor mulţimii I={1,2,…,n} (orice soluţie (
) a problemei iniţiale fiind obţinută din soluţia (i1, i2,…, im) a celei de a doua
problemă). Aranjamentele generate vor fi memorate succesiv într-un vector A cu m
componente.
Prezentăm în continuare algoritmul de generare în ordine lexicografică a
aranjamentelor de m elemente din mulţimea {1,2,…,n}. De exemplu, pentru n = 3 şi
m = 2 se va obţine în ordine: (1,2), (1,3), (2,1), (2,3), (3,1), (3,2).
Observaţie. Complexitatea temporală a algoritmilor bazaţi pe
generarea tuturor aranjamentelor este cel mult O(n!).
Program generare aranjamente

//Program GenerAranjamente
#include<iostream> void Aranj(int i)
using namespace std; {int j,k;
#define nmax 20 if (i==m+1) Scrie();
else for (j=1;j<=n;j+
int A[nmax];
+)
bool Disp[nmax];
if (Disp[j])
int i, n, m;
{ A[i]=j;
Disp[j]=false;
Aranj(i+1);
Disp[j]=true;}
}
Sfârşit

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