PIN kodovi
PIN ima k cifara (k ≤ 6), a dozvoljene su samo cifre iz date reči c (npr. 137). Ispiši sve moguće PIN-ove u rastućem poretku.
Primer
Ulaz
2 13Izlaz
11
13
31
33Mnogi takmičarski zadaci traže da se isprobaju svi rasporedi ili svi izbori elemenata. Ovde su gotovi šabloni za generisanje permutacija, kombinacija, varijacija i podskupova – rekurzivno i pomoću funkcije next_permutation.
| Šta biramo | Naziv | Broj | Primer za {1, 2, 3} |
|---|---|---|---|
| raspored svih n elemenata | permutacije | n! | 123, 132, 213, 231, 312, 321 |
| k od n, redosled nije bitan | kombinacije | C(n, k) | k = 2: 12, 13, 23 |
| k od n, redosled bitan | varijacije | n!/(n−k)! | k = 2: 12, 13, 21, 23, 31, 32 |
| k puta po jedan od n (sa ponavljanjem) | varijacije sa ponavljanjem | nk | k = 2: 11, 12, 13, 21, …, 33 |
| bilo koji izbor | podskupovi | 2n | {}, {1}, {2}, {3}, {1,2}, … |
Kako se ovi brojevi računaju bez generisanja, objašnjeno je u lekciji Kombinatorika.
Na svaku poziciju redom stavljamo jedan od još neiskorišćenih brojeva. Niz iskoriscen pamti koji su brojevi već u permutaciji.
#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> perm;
vector<bool> iskoriscen;
void generisi() {
if ((int)perm.size() == n) { // permutacija je kompletna
for (int x : perm) cout << x << " ";
cout << "\n";
return;
}
for (int x = 1; x <= n; x++) {
if (iskoriscen[x]) continue;
iskoriscen[x] = true; perm.push_back(x); // izaberi
generisi(); // istraži
iskoriscen[x] = false; perm.pop_back(); // poništi
}
}
int main() {
cin >> n;
iskoriscen.assign(n + 1, false);
generisi();
return 0;
}
Permutacije izlaze u leksikografskom poretku, jer se na svaku poziciju brojevi probaju od najmanjeg.
U C++-u funkcija next_permutation (zaglavlje <algorithm>) pretvara niz u sledeću permutaciju u leksikografskom poretku i vraća false kada je stigla do poslednje. Niz mora na početku biti sortiran. Ako u nizu ima jednakih elemenata, svaka različita permutacija dobija se tačno jednom.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s;
cin >> s;
sort(s.begin(), s.end()); // počinjemo od najmanje permutacije
int broj = 0;
do {
cout << s << "\n";
broj++;
} while (next_permutation(s.begin(), s.end()));
cout << "Ukupno: " << broj << endl;
return 0;
}
Kod kombinacija redosled nije bitan, pa da ne bismo dobili isti izbor dva puta, brojeve biramo rastuće: posle broja x sledeći biramo od x + 1.
#include <iostream>
#include <vector>
using namespace std;
int n, k;
vector<int> izbor;
void kombinacije(int od) {
if ((int)izbor.size() == k) {
for (int x : izbor) cout << x << " ";
cout << "\n";
return;
}
// odsecanje: ostalo je dovoljno brojeva da se izbor popuni
for (int x = od; x <= n - (k - (int)izbor.size()) + 1; x++) {
izbor.push_back(x);
kombinacije(x + 1);
izbor.pop_back();
}
}
int main() {
cin >> n >> k;
kombinacije(1);
return 0;
}
Podskup skupa od n elemenata može se predstaviti brojem od 0 do 2n − 1: ako je i-ti bit jedinica, element i je u podskupu. Ovo je kraće od rekurzije i dovoljno brzo za n ≤ 20.
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int maska = 0; maska < (1 << n); maska++) {
cout << "{ ";
for (int i = 0; i < n; i++)
if (maska & (1 << i)) // da li je i-ti bit jedinica
cout << i + 1 << " ";
cout << "}\n";
}
return 0;
}
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
PIN ima k cifara (k ≤ 6), a dozvoljene su samo cifre iz date reči c (npr. 137). Ispiši sve moguće PIN-ove u rastućem poretku.
2 1311
13
31
33Od cifara datog broja (najviše 9 cifara) treba složiti broj koji koristi sve cifre, deljiv je sa 3 i najveći je mogući. Ako takav ne postoji, ispiši -1.
1052-1123321Od n učenika (n ≤ 15) sa datim poenima bira se tim od tačno k učenika. Koliko ima timova čiji je zbir poena bar P?
4 2 9
5 3 6 44next_permutation niz mora biti sortiran na početku – inače se preskaču permutacije.od = x + 1), inače dobijaš varijacije sa duplikatima.1 << n je 2n; za n ≥ 31 koristi 1LL << n.1. Koliko ima permutacija skupa od 5 elemenata?
2. Šta vraća next_permutation kada je niz poslednja permutacija?
3. Koji broj predstavlja podskup {1, 3} skupa {1, 2, 3} u zapisu bitovima (bit 0 = element 1)?