Bun venit la fundamentele combinatoricii! Dacă permutările, aranjamentele și combinațiile sunt “clădirile”, atunci produsul cartezian și submulțimile sunt cărămizile din care sunt construite. Să explorăm aceste concepte fundamentale care stau la baza tuturor celorlalte!
1. Produsul Cartezian: “Toate Perechile Posibile”
Ce este produsul cartezian?
Definiție formală:
Produsul cartezian al două mulțimi A și B, notat A × B, este mulțimea tuturor perechilor ordonate (a, b) unde a ∈ A și b ∈ B.
Definiție pentru copii:
Dacă ai două cutii – una cu fructe, alta cu legume – produsul cartezian înseamnă să iei fiecare fruct și să-l combini cu fiecare legumă.
Exemplu concret:
A = {Mere, Pere}
B = {Morcovi, Castraveți}
A × B = {
(Mere, Morcovi),
(Mere, Castraveți),
(Pere, Morcovi),
(Pere, Castraveți)
}
Cum gândește calculatorul produsul cartezian?
Imaginează-ți două roți care se învârt:
Roata A: Mere, Pere
Roata B: Morcovi, Castraveți
Toate combinațiile:
Mere + Morcovi ✓
Mere + Castraveți ✓
Pere + Morcovi ✓
Pere + Castraveți ✓
Implementare în C++:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void produsCartezianSimplu() {
cout << "=== PRODUS CARTEZIAN SIMPLU ===\n\n";
vector<string> A = {"Mere", "Pere"};
vector<string> B = {"Morcovi", "Castraveti"};
cout << "A = {Mere, Pere}\n";
cout << "B = {Morcovi, Castraveti}\n\n";
cout << "A × B = {\n";
for(int i = 0; i < A.size(); i++) {
for(int j = 0; j < B.size(); j++) {
cout << " (" << A[i] << ", " << B[j] << ")\n";
}
}
cout << "}\n";
cout << "Cardinal: |A×B| = |A| × |B| = "
<< A.size() << " × " << B.size()
<< " = " << A.size() * B.size() << " perechi\n";
}
// Produs cartezian general pentru n mulțimi
void produsCartezianGeneral(vector<vector<string>>& multimi,
vector<string>& combinatieCurenta,
int nivel) {
if(nivel == multimi.size()) {
// Am completat o combinatie
cout << " (";
for(int i = 0; i < combinatieCurenta.size(); i++) {
cout << combinatieCurenta[i];
if(i < combinatieCurenta.size() - 1) {
cout << ", ";
}
}
cout << ")\n";
return;
}
for(int i = 0; i < multimi[nivel].size(); i++) {
combinatieCurenta.push_back(multimi[nivel][i]);
produsCartezianGeneral(multimi, combinatieCurenta, nivel + 1);
combinatieCurenta.pop_back(); // Backtrack
}
}
int main() {
cout << "=== PRODUS CARTEZIAN - CONCEPT FUNDAMENTAL ===\n\n";
// Exemplul simplu
produsCartezianSimplu();
cout << "\n\n=== PRODUS CARTEZIAN GENERAL ===\n\n";
// Exemplu cu 3 mulțimi
vector<vector<string>> multimi = {
{"Rosu", "Verde", "Albastru"}, // Culori
{"Mare", "Mic"}, // Marimi
{"Cerc", "Patrat"} // Forme
};
cout << "Multimea 1 (Culori): {Rosu, Verde, Albastru}\n";
cout << "Multimea 2 (Marimi): {Mare, Mic}\n";
cout << "Multimea 3 (Forme): {Cerc, Patrat}\n\n";
cout << "Produsul cartezian A×B×C = {\n";
vector<string> combinatieCurenta;
produsCartezianGeneral(multimi, combinatieCurenta, 0);
cout << "}\n\n";
// Calcul cardinal
long long cardinal = 1;
for(auto& multime : multimi) {
cardinal *= multime.size();
}
cout << "Cardinal total: ";
for(int i = 0; i < multimi.size(); i++) {
cout << multimi[i].size();
if(i < multimi.size() - 1) {
cout << " × ";
}
}
cout << " = " << cardinal << " combinatii\n";
return 0;
}
Aplicații practice ale produsului cartezian:
- Toate combinațiile de username + password
- Configurații de produse (culoare × mărime × model)
- Tabelă de adevăr în logică (true/false combinații)
- Coordonate într-un grid (toate perechile (x,y))
2. Submulțimile: “Toate Combinațiile Posibile”
Ce este o submulțime?
Definiție formală:
O submulțime a unei mulțimi A este o mulțime ale cărei elemente sunt toate conținute în A.
Definiție pentru copii:
Ai o cutie cu jucării. O submulțime înseamnă să alegi niște jucării din cutie (poate toate, poate unele, poate niciuna).
Exemplu concret:
A = {a, b, c}
Submulțimile lui A:
1. {} (mulțimea vidă)
2. {a}
3. {b}
4. {c}
5. {a, b}
6. {a, c}
7. {b, c}
8. {a, b, c} (întreaga mulțime)
Proprietăți importante ale submulțimilor:
- Orice mulțime este submulțime a ei însăși
- Mulțimea vidă ∅ este submulțime a oricărei mulțimi
- Numărul de submulțimi ale unei mulțimi cu n elemente este 2ⁿ
De ce 2ⁿ?
Fiecare element are 2 alegeri:
1. Să fie ÎN submulțime
2. Să NU fie în submulțime
Pentru n elemente: 2 × 2 × 2 × ... × 2 (de n ori) = 2ⁿ
Implementare generare submulțimi în C++:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
void afisareSubmultime(vector<int>& multime, int mask) {
cout << "{ ";
bool primul = true;
for(int i = 0; i < multime.size(); i++) {
if(mask & (1 << i)) { // Verifică dacă bitul i este 1
if(!primul) cout << ", ";
cout << multime[i];
primul = false;
}
}
if(primul) {
cout << "∅"; // Mulțimea vidă
}
cout << " }";
}
void submulțimiCuBiti(vector<int>& multime) {
cout << "=== SUBMULTIMI CU REPREZENTARE PE BITI ===\n\n";
int n = multime.size();
int totalSubmultimi = 1 << n; // 2ⁿ
cout << "Multimea A = { ";
for(int num : multime) {
cout << num << " ";
}
cout << "}\n\n";
cout << "Toate submulțimile (" << totalSubmultimi << "):\n";
for(int mask = 0; mask < totalSubmultimi; mask++) {
cout << mask + 1 << ". ";
afisareSubmultime(multime, mask);
cout << endl;
}
cout << "\nExplicatie reprezentare pe biti:\n";
cout << "mask = 0 (000 în binar) → {∅}\n";
cout << "mask = 1 (001) → {" << multime[0] << "}\n";
cout << "mask = 2 (010) → {" << multime[1] << "}\n";
cout << "mask = 3 (011) → {" << multime[0] << ", " << multime[1] << "}\n";
// ... și tot așa
}
void submulțimiBacktracking(vector<int>& multime,
vector<int>& subcurenta,
int start) {
// Afișează submulțimea curentă
cout << "{ ";
for(int i = 0; i < subcurenta.size(); i++) {
cout << subcurenta[i];
if(i < subcurenta.size() - 1) cout << ", ";
}
cout << " }\n";
// Generează următoarele submulțimi
for(int i = start; i < multime.size(); i++) {
subcurenta.push_back(multime[i]);
submulțimiBacktracking(multime, subcurenta, i + 1);
subcurenta.pop_back(); // Backtrack
}
}
int main() {
cout << "=== SUBMULTIMILE UNEI MULTIMI ===\n\n";
vector<int> multime = {1, 2, 3};
int n = multime.size();
cout << "TEORIE:\n";
cout << "Multimea A are " << n << " elemente\n";
cout << "Numar de submulțimi: 2^" << n << " = "
<< (1 << n) << "\n\n";
// Metoda 1: Cu biți
submulțimiCuBiti(multime);
cout << "\n\n=== METODA BACKTRACKING ===\n\n";
// Metoda 2: Backtracking
cout << "Generare recursiva:\n";
vector<int> subcurenta;
submulțimiBacktracking(multime, subcurenta, 0);
return 0;
}
3. Relația dintre Produs Cartezian și Submulțimi
Tabel comparativ:
| Aspect | Produs Cartezian | Submulțimi |
|---|---|---|
| Ce generează? | Perechi/tupluri ordonate | Selecții de elemente |
| Ordinea contează? | DA (a,b) ≠ (b,a) | NU {a,b} = {b,a} |
| Elemente repetate? | DA (dacă A și B au elemente comune) | NU (mulțimi nu au duplicate) |
| Cardinal | A×B | |
| Exemplu cu A={1,2} | A×A = {(1,1),(1,2),(2,1),(2,2)} | P(A) = {∅,{1},{2},{1,2}} |
Cum se raportează cele două concepte?
#include <iostream>
#include <vector>
using namespace std;
void demonstratieRelatie() {
cout << "=== RELATIA DINTRE PRODUS CARTEZIAN SI SUBMULTIMI ===\n\n";
vector<int> A = {1, 2};
cout << "MULTIMEA A = {1, 2}\n\n";
// 1. Produsul cartezian A × A
cout << "1. PRODUS CARTEZIAN A × A:\n";
cout << " A × A = {";
for(int a1 : A) {
for(int a2 : A) {
cout << "(" << a1 << "," << a2 << ") ";
}
}
cout << "}\n";
cout << " Cardinal: " << A.size() << " × " << A.size()
<< " = " << A.size() * A.size() << "\n\n";
// 2. Submulțimile lui A
cout << "2. SUBMULTIMILE LUI A (P(A)):\n";
cout << " P(A) = {∅, {1}, {2}, {1,2}}\n";
cout << " Cardinal: 2^" << A.size() << " = "
<< (1 << A.size()) << "\n\n";
// 3. Relația matematică
cout << "3. RELATIA MATEMATICA:\n";
cout << " |P(A)| = 2^|A|\n";
cout << " |A×A| = |A|^2\n";
cout << " Pentru |A|=n: |P(A)| = 2ⁿ, |A×A| = n²\n";
// 4. Comparație numerică
cout << "\n4. COMPARATIE NUMERICA:\n";
cout << " Pentru n=3: 2³ = 8, 3² = 9\n";
cout << " Pentru n=4: 2⁴ = 16, 4² = 16\n";
cout << " Pentru n=5: 2⁵ = 32, 5² = 25\n";
cout << " Pentru n=10: 2¹⁰ = 1024, 10² = 100\n";
cout << " Observatie: 2ⁿ crește MULT mai rapid decât n²!\n";
}
int main() {
demonstratieRelatie();
return 0;
}
4. Aplicații Practice Avansate
Aplicația 1: Generator de Parole
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void generatorParole() {
cout << "=== GENERATOR DE PAROLE (PRODUS CARTEZIAN) ===\n\n";
vector<string> cifre = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
vector<string> litereMici = {"a", "b", "c", "d", "e"};
vector<string> litereMari = {"A", "B", "C", "D", "E"};
vector<string> simboluri = {"!", "@", "#"};
vector<vector<string>> multimi = {cifre, litereMici, litereMari, simboluri};
cout << "Generam parole de forma: [cifra][litera mica][litera mare][simbol]\n\n";
int contor = 0;
int maximAfisare = 20; // Afișăm doar primele 20 pentru claritate
// Produs cartezian cu 4 mulțimi
for(const auto& c : cifre) {
for(const auto& lm : litereMici) {
for(const auto& lM : litereMari) {
for(const auto& s : simboluri) {
contor++;
if(contor <= maximAfisare) {
cout << "Parola " << contor << ": "
<< c << lm << lM << s << endl;
}
}
}
}
}
cout << "\n... și încă " << (cifre.size() * litereMici.size() *
litereMari.size() * simboluri.size() - maximAfisare)
<< " altele...\n";
long long total = cifre.size() * litereMici.size() *
litereMari.size() * simboluri.size();
cout << "\nNumar total de parole posibile: ";
cout << cifre.size() << " × " << litereMici.size() << " × "
<< litereMari.size() << " × " << simboluri.size()
<< " = " << total << " parole\n";
cout << "\nATENTIE la 'explozia combinatorica'!\n";
cout << "Daca avem 10 cifre, 26 litere mici, 26 litere mari, 10 simboluri:\n";
cout << "10 × 26 × 26 × 10 = " << 10*26*26*10 << " parole!\n";
}
int main() {
generatorParole();
return 0;
}
Aplicația 2: Sistem de Recomandări
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void sistemRecomandari() {
cout << "=== SISTEM DE RECOMANDARI (SUBMULTIMI) ===\n\n";
// Produse disponibile în magazin
vector<string> produse = {
"Laptop", "Telefon", "Tableta",
"Casti", "Incarcator", "Husa"
};
// Bugetul clientului
const int BUGET_MAXIM = 1500;
// Preturile produselor
vector<int> preturi = {1000, 800, 600, 100, 50, 30};
cout << "Produse disponibile:\n";
for(int i = 0; i < produse.size(); i++) {
cout << " " << i+1 << ". " << produse[i]
<< " - " << preturi[i] << " RON\n";
}
cout << "\nBuget client: " << BUGET_MAXIM << " RON\n\n";
// Generăm toate submulțimile de produse
int totalSubmultimi = 1 << produse.size();
int recomandariValide = 0;
cout << "Recomandari posibile (submultimi care nu depasesc bugetul):\n\n";
for(int mask = 1; mask < totalSubmultimi; mask++) {
vector<string> cos;
int costTotal = 0;
for(int i = 0; i < produse.size(); i++) {
if(mask & (1 << i)) {
cos.push_back(produse[i]);
costTotal += preturi[i];
}
}
if(costTotal <= BUGET_MAXIM && !cos.empty()) {
recomandariValide++;
cout << "Recomandare " << recomandariValide << ":\n";
cout << " Produse: ";
for(const auto& produs : cos) {
cout << produs << " ";
}
cout << "\n Cost total: " << costTotal << " RON\n";
cout << " Economisit: " << BUGET_MAXIM - costTotal << " RON\n\n";
}
}
cout << "Total recomandari valide: " << recomandariValide
<< " din " << totalSubmultimi - 1 << " submulțimi posibile\n";
}
int main() {
sistemRecomandari();
return 0;
}
5. Proprietăți Matematice Importante
Proprietăți ale produsului cartezian:
- A × B ≠ B × A (nu este comutativ)
- (a,b) ≠ (b,a) dacă a ≠ b
- |A × B| = |A| × |B| (cardinalitatea)
- A × (B ∪ C) = (A × B) ∪ (A × C) (distributivitate)
- A × ∅ = ∅ (produsul cu mulțimea vidă)
Proprietăți ale submulțimilor:
- ∅ ⊆ A pentru orice A
- A ⊆ A (reflexivitate)
- Dacă A ⊆ B și B ⊆ C, atunci A ⊆ C (tranzitivitate)
- P(A) are 2|A| elemente
Demonstrație matematică:
#include <iostream>
#include <cmath>
using namespace std;
void demonstratiiMatematice() {
cout << "=== DEMONSTRATII MATEMATICE ===\n\n";
cout << "1. DE CE |P(A)| = 2^|A| ?\n";
cout << " Fiecare element din A are 2 optiuni:\n";
cout << " - Sa fie IN submulțime\n";
cout << " - Sa fie IN AFARA submulțimii\n";
cout << " Pentru n elemente: 2 × 2 × ... × 2 = 2^n\n\n";
cout << "2. DE CE A × B ≠ B × A ?\n";
cout << " Exemplu: A = {1}, B = {2}\n";
cout << " A × B = {(1,2)}\n";
cout << " B × A = {(2,1)}\n";
cout << " (1,2) ≠ (2,1) deci A×B ≠ B×A\n\n";
cout << "3. COMPARATIE CRESTERE:\n";
cout << " |P(A)| = 2^n crește EXPONENȚIAL\n";
cout << " |A×A| = n^2 crește POLINOMIAL\n\n";
cout << " n | 2^n | n^2 | Raport 2^n/n^2\n";
cout << " ------------------------------------\n";
for(int n = 1; n <= 10; n++) {
double putere = pow(2, n);
double patrat = n * n;
double raport = putere / patrat;
cout << " " << n << " | " << (int)putere << " | "
<< (int)patrat << " | " << raport << endl;
}
cout << "\n Concluzie: 2^n devine MULȚI mai mare!\n";
}
int main() {
demonstratiiMatematice();
return 0;
}
6. Algoritmi Avansați și Optimizări
Generare eficientă a submulțimilor cu Gray Code:
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
void submulțimiGrayCode(int n) {
cout << "=== SUBMULTIMI CU GRAY CODE ===\n\n";
cout << "Generare în ordine Gray (o singură diferență între consecutive):\n\n";
vector<int> current;
for(int i = 0; i < (1 << n); i++) {
// Convertim la Gray code: g = i ^ (i >> 1)
int gray = i ^ (i >> 1);
// Afișăm submulțimea
cout << i + 1 << ". { ";
current.clear();
for(int bit = 0; bit < n; bit++) {
if(gray & (1 << bit)) {
current.push_back(bit + 1);
}
}
for(int j = 0; j < current.size(); j++) {
cout << current[j];
if(j < current.size() - 1) cout << ", ";
}
if(current.empty()) cout << "∅";
cout << " }";
// Afișăm reprezentarea binară
cout << " (Gray: ";
for(int bit = n-1; bit >= 0; bit--) {
cout << ((gray >> bit) & 1);
}
cout << ")\n";
}
}
int main() {
submulțimiGrayCode(3);
return 0;
}
Produs cartezian cu memoizare pentru mulțimi mari:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
map<vector<int>, vector<vector<int>>> memo;
vector<vector<int>> produsCartezianMemo(vector<vector<int>>& multimi, int nivel) {
// Dacă am calculat deja, returnăm din memorie
vector<int> key = {nivel};
for(auto& m : multimi) {
key.push_back(m.size());
}
if(memo.find(key) != memo.end()) {
return memo[key];
}
vector<vector<int>> result;
if(nivel == multimi.size()) {
result.push_back(vector<int>());
return result;
}
vector<vector<int>> subresult = produsCartezianMemo(multimi, nivel + 1);
for(int val : multimi[nivel]) {
for(auto& sub : subresult) {
vector<int> comb = {val};
comb.insert(comb.end(), sub.begin(), sub.end());
result.push_back(comb);
}
}
memo[key] = result;
return result;
}
int main() {
cout << "=== PRODUS CARTEZIAN CU MEMOIZARE ===\n\n";
vector<vector<int>> multimi = {
{1, 2, 3},
{4, 5},
{6, 7, 8}
};
auto result = produsCartezianMemo(multimi, 0);
cout << "Multimea 1: {1, 2, 3}\n";
cout << "Multimea 2: {4, 5}\n";
cout << "Multimea 3: {6, 7, 8}\n\n";
cout << "Primele 10 combinatii din " << result.size() << " total:\n";
for(int i = 0; i < min(10, (int)result.size()); i++) {
cout << i+1 << ". (";
for(int j = 0; j < result[i].size(); j++) {
cout << result[i][j];
if(j < result[i].size() - 1) cout << ", ";
}
cout << ")\n";
}
if(result.size() > 10) {
cout << "... si inca " << result.size() - 10 << " altele\n";
}
cout << "\nCardinal total: "
<< multimi[0].size() << " × "
<< multimi[1].size() << " × "
<< multimi[2].size() << " = "
<< result.size() << " combinatii\n";
return 0;
}
7. Tabel Sinoptic Final
| Concept | Definiție | Notație | Cardinal | Exemplu cu {1,2} |
|---|---|---|---|---|
| Produs Cartezian A×B | Toate perechile (a,b) cu a∈A, b∈B | A × B | A | |
| Puterea unei mulțimi P(A) | Mulțimea tuturor submulțimilor lui A | P(A) sau 2A | 2 | A |
| Submulțime propriu-zisă | Submulțime ≠ A | ⊂ | 2 | A |
| Mulțimea vidă | Submulțime cu 0 elemente | ∅ | 1 | ∅ |
8. Exerciții Practice și Probleme
Problema 1: Meniu Restaurant
Un restaurant oferă:
- Antreuri: Salată, Supă
- Fel principal: Pui, Vita, Peste
- Desert: Ingheata, Tort
Câte meniuri complete (antreu + fel principal + desert) pot fi alese?
Problema 2: Seturi de Învățare
Ai 5 cărți de matematică. În câte moduri poți alege cărțile
pentru a le lua la bibliotecă?
Problema 3: Configurații Calculator
Componente disponibile:
- Procesor: i5, i7, Ryzen5
- RAM: 8GB, 16GB, 32GB
- SSD: 256GB, 512GB, 1TB
Câte configurații unice pot fi construite?
Soluții implementate:
#include <iostream>
#include <vector>
using namespace std;
void rezolvareProbleme() {
cout << "=== REZOLVARE PROBLEME PRACTICE ===\n\n";
// Problema 1: Meniu restaurant
cout << "PROBLEMA 1: MENIU RESTAURANT\n";
cout << "Antreuri: 2 (Salata, Supa)\n";
cout << "Fel principal: 3 (Pui, Vita, Peste)\n";
cout << "Desert: 2 (Ingheata, Tort)\n";
int meniuri = 2 * 3 * 2;
cout << "Meniuri posibile: 2 × 3 × 2 = " << meniuri << "\n\n";
// Problema 2: Cărți bibliotecă
cout << "PROBLEMA 2: CARTI BIBLIOTECA\n";
cout << "Avem 5 carti de matematica.\n";
cout << "Submultimile posibile (inclusiv niciuna si toate): 2^5 = "
<< (1 << 5) << "\n";
cout << "Dar vrem cel putin o carte: 2^5 - 1 = "
<< (1 << 5) - 1 << " variante\n\n";
// Problema 3: Configurații calculator
cout << "PROBLEMA 3: CONFIGURATII CALCULATOR\n";
cout << "Procesor: 3 optiuni\n";
cout << "RAM: 3 optiuni\n";
cout << "SSD: 3 optiuni\n";
int configuratii = 3 * 3 * 3;
cout << "Configuratii unice: 3 × 3 × 3 = " << configuratii << "\n";
cout << "Produs cartezian P×R×S cu |P|=3, |R|=3, |S|=3\n\n";
// Problema bonus: Parole
cout << "PROBLEMA BONUS: PAROLE Sigure\n";
cout << "O parola de 8 caractere cu:\n";
cout << "- 10 cifre (0-9)\n";
cout << "- 26 litere mici (a-z)\n";
cout << "- 26 litere mari (A-Z)\n";
cout << "- 10 simboluri speciale\n";
long long totalCaractere = 10 + 26 + 26 + 10;
long long parole = 1;
for(int i = 0; i < 8; i++) {
parole *= totalCaractere;
}
cout << "Caractere totale: " << totalCaractere << "\n";
cout << "Parole posibile: " << totalCaractere << "^8 = ";
// Afișare în format științific pentru numere mari
if(parole > 1000000) {
cout << parole / 1000000 << " milioane";
} else {
cout << parole;
}
cout << "\n";
}
int main() {
rezolvareProbleme();
return 0;
}
9. Concluzie și Reguli Practice
Când folosești fiecare concept:
- Folosește PRODUSUL CARTEZIAN când:
- Ai mai multe alegeri independente
- Vrei toate combinațiile posibile
- Ordinea perechilor contează
- Exemplu: alegere meniu, configurații produse
- Folosește SUBMULȚIMILE când:
- Selectezi elemente dintr-o singură mulțime
- Ordinea NU contează
- Vrei toate selecțiile posibile (inclusiv niciuna)
- Exemplu: alegere cărți, selecție produse în coș
Reguli de aur pentru programare:
// 1. ATENȚIE la "explozia combinatorică"!
// Produs cartezian: |A|×|B|×|C|... crește FOARTE repede
// 2. Pentru submulțimi: 2^n devine imens pentru n>20
// n=20 → 1.048.576 submulțimi
// n=30 → 1.073.741.824 submulțimi!
// 3. Folosește reprezentarea pe biți pentru submulțimi
// Eficientă și elegantă pentru n ≤ 64
// 4. Pentru produse carteziene mari, generează doar ce ai nevoie
// Nu stoca toate combinațiile în memorie dacă nu e necesar
// 5. Tehnici de optimizare:
// - Pruning (elimină combinații imposibile devreme)
// - Memoizare (salvează rezultate calculate)
// - Generare leneșă (generează doar la cerere)
Exercițiu final de sinteză:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
cout << "=== EXERCIȚIU FINAL - SINTEZĂ ===\n\n";
cout << "SCENARIU: Planificare vacanță\n\n";
cout << "Optiuni disponibile:\n";
cout << "1. Destinații: {Munte, Mare, CityBreak}\n";
cout << "2. Durată: {3zile, 5zile, 7zile}\n";
cout << "3. Sezon: {Vara, Iarna}\n";
cout << "4. Activitate: {Relaxare, Aventura, Cultural}\n\n";
// Calcul produs cartezian
int destinatii = 3;
int durate = 3;
int sezoane = 2;
int activitati = 3;
int varianteVacanta = destinatii * durate * sezoane * activitati;
cout << "Variante de vacanță posibile:\n";
cout << destinatii << " × " << durate << " × "
<< sezoane << " × " << activitati
<< " = " << varianteVacanta << " variante\n\n";
// Submulțimi pentru pachet optional
cout << "PACHETE OPTIONALE (alege oricare):\n";
cout << "{Asigurare, Transfer, Ghid, Masina}\n\n";
int pacheteOptionale = 4;
int submultimiPachete = 1 << pacheteOptionale;
cout << "Combinații pachete optionale: 2^" << pacheteOptionale
<< " = " << submultimiPachete << " (inclusiv niciunul)\n\n";
// Total combinații complete
cout << "TOTAL COMBINAȚII COMPLETE:\n";
cout << "Variante vacanță × Combinații pachete =\n";
cout << varianteVacanta << " × " << submultimiPachete
<< " = " << varianteVacanta * submultimiPachete
<< " combinații unice!\n\n";
cout << "=== CONCLUZIE ===\n";
cout << "Produsul cartezian și submulțimile sunt peste tot\n";
cout << "în viața reală, de la planificarea vacanțelor\n";
cout << "până la configurarea produselor online!\n";
return 0;
}
Remember: Produsul cartezian și submulțimile sunt fundamentale pentru înțelegerea combinatoricii. Masterizează aceste concepte, și vei putea aborda cu încredere orice problemă de selecție sau combinare! 🧩🔢✨
Leave a Reply