Sunteți pe pagina 1din 56

Backtracking simplu

1. Se citeşte un număr natural nenul n. Să se afişeze, în ordine lexicografică, permutările mulţimii {1,2,..,n}.


#include <fstream>
using namespace std;
int st[100],n,nrsol;
ifstream fin("permutari.in");
ofstream fout("permutari.out");
void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0; //daca se repeta numere nu e valid
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
{if (k==n)//am solutie
afisare(k);
else back(k+1);} //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n;
back(1);

return 0;
}
2. Se citeşte un număr natural nenul n. Să se afişeze, în ordine invers lexicografică, permutările mulţimii {1,2,..,n}.
#include <fstream>
using namespace std;
int st[100],n,nrsol;
ifstream fin("permutari1.in");
ofstream fout("permutari1.out");
void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0; //daca se repeta numere nu e valid
return 1; //e valid
}

void back(int k)
{
for(int i=n;i>=1;i--) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n;
back(1);

return 0;
}
3. Se citeşte un număr natural nenul n, apoi n numere naturale distincte. Să se afişeze, în ordine lexicografică, permutările
mulţimii formate din cele n numere citite.
#include <fstream>
#include<bits/stdc++.h>
using namespace std;
int st[100],n,nrsol, v[100];
ifstream fin("permutari2.in");
ofstream fout("permutari2.out");
void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0; //daca se repeta numere nu e valid
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=v[i];
if(valid(k)==1) //daca valoarea e valida
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n;
for(int i=1;i<=n;i++)
{
fin>>v[i];
}
sort(v+1,v+n+1);
back(1);

return 0;
}
4. Se citeşte un număr natural nenul n. Să se afişeze, în ordine lexicografică, permutările fără puncte fixe ale
mulţimii {1,2,..,n}.
#include <fstream>
using namespace std;
int st[100],n,nrsol;
ifstream fin("permpf.in");
ofstream fout("permpf.out");
void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0; //daca se repeta numere nu e valid
if(st[k]==k) return 0;
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n;
back(1);
return 0;
}
5. Se citește un număr natural n (n<16). Afișați în ordine lexicografică toate permutările mulțimii {1,2,…,n} în care
elementele pare sunt puncte fixe (nu își schimbă poziția).
#include <iostream>
using namespace std;
int st[100],n,nrsol;
void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0;
if(k%2==0 && st[k]!=k) return 0;//daca se repeta numere nu e valid
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n;
back(1);

return 0;
}
6. Să se genereze toate anagramele unui cuvânt citit.
#include <bits/stdc++.h>
using namespace std;
int j=0,k=0;
char st[100],v[100],n;
ifstream fin ("anagrame1.in");
ofstream fout ("anagrame1.out");
void afisare(int k)
{
for(int i=0;i<=k;i++)
fout<<st[i];
fout<<endl;
}
int valid(int k)
{ for(int i=0;i<k;i++)
if (st[k]==st[i])
return 0;
return 1;
}

void back(int k)
{
for(int i=0;i<j;i++)
{ st[k]=v[i];
if(valid(k)==1)
if (k==j-1)
afisare(k);
else back(k+1);
}
}

int main()
{ while(fin>>n)
{

v[j]=n;j++;

for( int i=0;i<j-1;i++)


for( int p=i+1;p<j;p++)
if(v[i]>v[p])
swap(v[i],v[p]);

back(0);
return 0;
}
7. Se citește un cuvânt format din cel puțin două și cel mult zece caractere litere mici distincte care conține cel puțin două
vocale. Afișați în ordine lexicografică anagramele cuvântului citit care au proprietatea că încep și se termină cu o vocală.
#include <bits/stdc++.h>
using namespace std;
int n,j;
char st[101];
char v[11];
//ifstream fin("permutari2.in");
//ofstream fout("permutari2.out");
void afisare(int k)
{

cout<<st;
cout<<'\n';

int valid(int k)
{ for(int i=0;i<k;i++)
if (st[k]==st[i])
return 0;
if(k==0 && strchr("aeiou",st[k])==NULL)
return 0;
if(k==j-1 && strchr("aeiou",st[k])==NULL)
return 0;

return 1;
}

void back(int k)
{ for(int i=0;i<j;i++)
{
st[k]=v[i];
if(valid(k)==1)
if (k==j-1)
afisare(k);
else back(k+1);
}
}

int main()
{

//int i=0;

cin >>v;
j=strlen(v);

sort(v,v+j);
back(0);

return 0;
}
8. Se citește un număr natural n având cifrele diferite două câte două. Afișați în ordine crescătoare numerele care se pot
obține din cifrele lui n și care au același număr de cifre ca n.
#include <fstream>
#include<bits/stdc++.h>
using namespace std;
int st[100],n,nrsol, v[100];
int h=1;
void afisare(int k)
{
for(int i=1;i<=k;i++)
cout<<st[i];
cout<<'\n';
}

int valid(int k)
{ for(int i=1;i<k;i++)
if (st[k]==st[i])
return 0;
if(st[1]==0) return 0;
return 1;
}

void back(int k)
{
for(int i=1;i<h;i++)
{ st[k]=v[i];
if(valid(k)==1)
if (k==h-1)
afisare(k);
else back(k+1);
}
}
int main()
{

cin>>n;
while(n)
{

v[h]=n%10;
n=n/10;
h++;

}
sort(v+1,v+h);
back(1);

return 0;
}
9. Se citesc două numere naturale nenule n și k. Să se afişeze, în ordine lexicografică, submulțimile de câte k elemente ale
mulţimii {1,2,..,n}. (combinari)
#include <bits/stdc++.h>
using namespace std;
int st[100],n,m;
ifstream fin("combinari.in");
ofstream fout("combinari.out");
void afisare(int k)
{ //nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

//int valid(int k)
//{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
// if (st[k]==st[i])
// return 0; //daca se repeta numere nu e valid
/// if (k>=2 && st[k]<st[k-1]) return 0; //sa fie in ordine crescatoare
// return 1; //e valid
//}

//alta varianta in vare am combinat cele doua conditii


int valid(int k)
{
if (k>=2 && st[k]<=st[k-1]) return 0; //sa fie in ordine crescatoare
return 1; //e valid
}
void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n>>m;
back(1);
//cout<<"nr de solutii:"<<nrsol;
return 0;
}
10. Se citesc două numere naturale nenule n și m. Să se determine toate şirurile cu m elemente din mulţimea {1,2,..,n},
ordonate strict crescător, cu proprietatea că oricare două elemente consecutive în şir au diferenţa mai mică sau egală cu
cu 2.
#include <bits/stdc++.h>
using namespace std;
ifstream fin("siruri.in");
ofstream fout("siruri.out");
int st[100],n,k;

void afisare(int p)
{
for(int i=1;i<=p;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int p)
{
if(p>=2 && st[p]<=st[p-1]) return 0;
if(p>=2 && st[p]-st[p-1]>2) return 0;
return 1;
}

void back(int p)
{
for(int i=1;i<=n;i++)
{ st[p]=i;
if(valid(p)==1)
if (p==k)
afisare(p);
else back(p+1);
}
}
int main()
{ fin>>n>>k;
back(1);
return 0;
}
11. Se citesc două numere naturale n și m. Afișați în ordine lexicografică toate submulțimile cu m elemente ale
mulțimii {1, 2, ..., n} în care nu există două elemente pare alăturate.
#include <iostream>
using namespace std;
int st[100],n,m,nrsol;

void afisare(int k)
{ //nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

int valid(int k)
{
if (k>=2 && st[k]<=st[k-1]) return 0; //sa fie in ordine crescatoare
if (k>=2 && st[k-1]%2==0 && st[k]%2==0) return 0;
return 1; //e valid
}
void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n>>m;
back(1);
//cout<<"nr de solutii:"<<nrsol;
return 0;
}
12. Să se determine toate submulţimile cu m elemente ale mulţimii divizorilor unui număr X natural dat.
#include <bits/stdc++.h>
using namespace std;
ifstream fin("submdiv.in");
ofstream fout("submdiv.out");

int st[100],n,m,v[100],l,x,ok;

void afisare(int k)
{
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

void divizori(int x)
{
int i;
for(i=1;i<=x;i++)
if(x%i==0)
v[++l]=i;
}

int valid(int k)
{
if (k>=2 && st[k]<=st[k-1]) return 0;
return 1;
}
void back(int k)
{
for(int i=1;i<=l;i++)
{ st[k]=v[i];
if(valid(k)==1)
if (k==m){
afisare(k);
ok=1;
}
else back(k+1);
}
}
int main()
{
fin>>x;
fin>>m;
divizori(x);
back(1);
if(ok==0) fout<<"fara solutie";

return 0;
}
13. Se dă un număr natural n. Afișați în ordine lexicografică toate secvențele de cifre binare care au atâtea cifre de 0 și
atâtea cifre de 1 câte are reprezentarea binară a lui n.
#include<bits/stdc++.h>
using namespace std;

int st[100],n,i,rez=0,p=1,m,u=0,v[1000],c0=0, c1=0;

void afisare(int k)
{ //nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i];
cout<<'\n';
}

int valid(int k)
{
int c00=0, c11=0;
for(int i=1;i<=k;i++)
{if (st[i]==0) c00++;
else c11++;}
if(c00>c0 || c11>c1) return 0;
return 1;
}

void back(int k)
{
for(int i=0;i<=1;i++) //pun pe fiecare nivel valori de la 1 la n
{
st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==u)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}

int main()
{
cin>>n;
m=n;
while(m)
{
v[++u]=m%2;
if(m%2==0) c0++;
else c1++;

m=m/2;
}
for(int i=1;i<u;i++)
for(int j=i+1;j<=u;j++)
if(v[i]>v[j])
swap(v[i],v[j]);
back(1);

return 0;
}
14. Se dau n mulțimi. Să se genereze în ordine lexicografică elementele produsului cartezian al mulțimilor date.
#include <iostream>
#include<fstream>
using namespace std;
int st[100],v[100],n,nrsol;

ifstream fin("produscartezian2.in");
ofstream fout("produscartezian2.out");

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

void back(int k)
{
for(int i=1;i<=v[k];i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n;
for(int i=1;i<=n;i++)
fin>>v[i];
back(1);
//cout<<"nr de solutii:"<<nrsol;
return 0;
}
15. Se dau două cifre a b și un număr n. Să se genereze toate numerele cu exact n cifre cuprinse între a și b.
#include <iostream>
#include <fstream>
using namespace std;
int st[100],n,m,nrsol,a,b;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i];
cout<<endl;
}
int valid(int k)
{ //daca se repeta numere nu e valid
return 1; //e valid
}

void back(int k)
{
for(int i=a;i<=b;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>a>>b>>n;
back(1);
//cout<<"nr de solutii:"<<nrsol;
return 0;
}
16. Se n și m numere naturale. Afișați în ordine lexicografică toate șirurile de lungime m care conțin numere de la 1 la n și
fiecare valoare apare de maxim două ori.
#include <iostream>
#include <fstream>
using namespace std;
int st[100],n,m,nrsol;

ifstream fin("2gen.in");
ofstream fout("2gen.out");

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{ for(int x=1;x<=n;x++)
{ int t=0;
for(int i=1;i<=k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[i]==x) t++;
if(t>2) return 0; //daca se repeta numere nu e valid
}
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n>>m;
back(1);
//cout<<"nr de solutii:"<<nrsol;
return 0;
}
17. Se dau n și m numere naturale. Afișați în ordine lexicografică toate șirurile de lungime m care conțin numere de
la 1 la n și au urmatoarea proprietate: orice element al unei soluții este mai mare sau egal cu elementul anterior sau este
mai mic decât elementul anterior cu 1.
#include <iostream>
#include <fstream>
using namespace std;
int st[100],n,m,nrsol;

ifstream fin("2genc.in");
ofstream fout("2genc.out");

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{
if(k>=2)
// if(st[k]-1!=st[k-1]) return 0;
// else
if(st[k]<st[k-1]-1) return 0;
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n>>m;
back(1);
//cout<<"nr de solutii:"<<nrsol;
return 0;
}
18. Problema Regine
19. Se citește de la tastatură un cuvânt s format din cel mult 11 litere mici distincte. Să se genereze în ordine alfabetică și
să se afișeze toate anagramele cuvântului s în care consoanele sunt puncte fixe.
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,st[100],nrsol=0,p[100];
char cuv[100],cuv1[100];

void afisare(int k)
{
int i;
nrsol++;
for(i=0;i<=k;i++)
cout<<cuv[st[i]];
cout<<'\n';
}

int valid(int k)
{
//puncte fixe
if (strchr("aeiou",cuv[st[k]])==0 && cuv[k]!=cuv[st[k]])
return 0;
return 1;
}

void back(int k)
{
for(int i=0;i<n;i++)
if (p[i]==0)
{
st[k]=i; p[i]=1;
if (valid(k))
{if (k==n-1) afisare(k);
else back(k+1);
}
p[i]=0;
}
}

int main()
{ cin>>cuv; //strcpy(cuv1,cuv);
n=strlen(cuv);
for(int i=0;i<n-1;i++) //sortez doar vocalele
for(int j=i+1;j<n;j++)
if (cuv[i]>cuv[j] && strchr ("aeiou",cuv[i]) && strchr("aeiou",cuv[j]))
swap(cuv[i],cuv[j]);
back(1);
}
20. Se citește o multime cu n numere naturale. Afișați toate permutările mulțimii citite în care elementul minim nu își
schimbă poziția.
#include <bits/stdc++.h>
using namespace std;

int st[100],n,mini=2000000000,poz,v[100],aux[100],t;

void afisare(int k)
{
for(int i=1;i<=k;i++)
if (i!=poz) cout<<aux[st[i]]<<" ";
else cout<<mini<<" "<<aux[st[i]]<<" ";
cout<<'\n';
}

int valid(int k)
{
for(int i=1;i<k;i++)
if (st[k]==st[i])
return 0;
return 1;
}

void back(int k)
{
for(int i=1;i<=t;i++)
{ st[k]=i;
if(valid(k))
if (k==t)
afisare(k);
else back(k+1);
}
}
int main()
{ cin>>n;
for(int i=1;i<=n;i++)
{ cin>>v[i];
if (v[i]<mini)
{ mini=v[i];
poz=i;
}
}
for(int i=1;i<=n;i++)
if (v[i]!=mini) aux[++t]=v[i];
sort(aux+1,aux+t+1);
back(1);
return 0;
}
21. Se consideră un cuvânt C format din litere mici, nu neapărat distincte. Să se afișeze în ordine lexicografică toate
cuvintele distincte formate cu exact aceleași caractere ca și C.
#include <bits/stdc++.h>

using namespace std;

ifstream fin("permrep.in");
ofstream fout("permrep.out");

int n , p[30];
char s[256] , cuv[256];

void afis()
{
for(int i = 1 ; i <= n ; i++)
fout << s[i];
fout << '\n';
}
void back(int k)
{
for(int i = 0 ; i < 30 ; i++)
if(p[i] > 0)
{
p[i]--;
s[k] = i + 'a';
if(k == n) afis();
else back(k + 1);
p[i]++;
}
}

int main()
{
fin >> cuv;
n = strlen(cuv);
for(int i = 1; i <= n; ++ i) p[cuv[i - 1] - 'a'] ++;
back(1);
return 0;
}
22. Se dau n numere naturale. Determinaţi o aranjare a acestor numere pe un cerc, astfel încât suma produselor de câte
două numere vecine să fie maximă.
#include <bits/stdc++.h>

using namespace std;

ifstream fin("cerc.in");
ofstream fout("cerc.out");

int n , x[20] , a[20] , rez[20] , p[20] , maxi;

void afisare()
{
for(int i = 1 ; i <= n ; i++)
fout << a[x[i]] << " ";
fout << '\n';
}

int suma()
{
int s = 0;
s += a[x[1]] * a[x[n]];
for(int i = 2 ; i <= n ; i++)
s += a[x[i]] * a[x[i - 1]];
return s;
}

void back(int k)
{
for(int i = 1 ; i <= n ; i++)
if(!p[i])
{
x[k] = i;
p[i] = 1;
if(k == n)
{
if(suma() > maxi)
{
maxi = suma();
for(int q = 1 ; q <= n ; q++)
rez[q] = x[q];
}
}
else back(k + 1);
p[i] = 0;
}
}

int main()
{
fin >> n;
for(int i = 1 ; i <= n ; i++)
fin >> a[i];
sort(a + 1 , a + n + 1);
x[1] = 1;
back(2);
for(int i = 1 ; i <= n ; i++)
fout << a[rez[i]] << " ";
return 0;
}
23. Se citesc două numere naturale nenule n și k. Să se afişeze, în ordine lexicografică, aranjamentele de câte k elemente
ale mulţimii {1,2,..,n}.
#include <iostream>
#include <fstream>
using namespace std;
int st[100],n,m,nrsol;

ifstream fin("aranjamente.in");
ofstream fout("aranjamente.out");

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0; //daca se repeta numere nu e valid
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n>>m;
back(1);
//cout<<"nr de solutii:"<<nrsol;
return 0;
}
24. Se citesc un număr natural n având cifrele diferite două câte două și o cifră c. Afișați în ordine crescătoare numerele
formate din c cifre distincte care se pot obține din cifrele lui n.
#include <bits/stdc++.h>
using namespace std;
int n , m , a[30] , x[30] , p[30] , cnt,c;
void afisare()
{
for(int i = 1 ; i <= c ; i++)
cout << a[x[i]];
cout << '\n';
}
void back(int k)
{
for(int i = 1 ; i <= cnt ; i++)
if(!p[i])
{
x[k] = i;
p[i] = 1;
if(k == 1 && a[i] == 0);
else
{
if(k == c) afisare();
else back(k + 1);
}
p[i] = 0;
}
}
int main()
{
cin >> n>>c;
while(n != 0)
{
a[++cnt] = n % 10;
n /= 10;
}
sort(a + 1 , a + cnt + 1);
back(1);
}
25. Se citeşte un număr natural nenul n, apoi n numere naturale distincte. Să se afişeze, în ordine lexicografică, șirurile din
cele n valori cu proprietatea că oricare două valori învecinate sunt prime între ele.
#include<bits/stdc++.h>
using namespace std;
int st[1000], n,a,b,v[1000];

ifstream fin("sirpie.in");
ofstream fout("sirpie.out");

int cmmdc(int a , int b)


{
int r;
while(b != 0)
{
r = a % b;
a = b;
b = r;
}
if(a == 1)return 1;
else return 0;
}

void afisare(int k)
{
for(int i=1; i<=k; i++)
fout<<st[i]<<' ';
fout<<'\n';
}

int valid(int k)
{
for(int i=1;i<k;i++)
{
if (st[k]==st[i])
return 0;
}
if(k>=2 && cmmdc(st[k], st[k-1])==0) return 0;
return 1;
}

void back(int k)
{
for(int i=1; i<=n; i++)
{
st[k]=v[i];
if(valid(k)==1)
if(k==n)
afisare(k);
else back(k+1);
}
}

int main()
{
fin>>n;
for(int i=1; i<=n; i++)
fin>>v[i];
sort(v+1, v+n+1);
back(1);
}
26. Se citește un număr natural nenul n. Să se afişeze, în ordine lexicografică, toate submulțimile nevide ale
mulţimii {1,2,..,n}.
#include <bits/stdc++.h>
using namespace std;

ifstream fin("submultimi.in");
ofstream fout("submultimi.out");

int x[10] , n;

void afisare(int k)
{
for(int i = 1 ; i <= k ; ++i)
fout << x[i] << ' ';
fout << '\n';
}

void back(int k)
{
for(int i = x[k - 1] + 1 ; i <= n ; ++i)
{
x[k] = i;
afisare(k);
back(k + 1);
}
}

int main()
{
fin >> n;
back(1);
return 0;
}
27. Se dau două numere naturale nenule n și m. Considerăm mulțimea A={1,2,..,n}. Să se genereze în ordine lexicografică
elementele produsului cartezian Am=A×A×⋯×A.
#include <iostream>
#include<fstream>
using namespace std;
int st[100],v[100],n,nrsol,m;

ifstream fin("produscartezian1.in");
ofstream fout("produscartezian1.out");

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ fin>>n>>m;
//for(int i=1;i<=n;i++)
//fin>>v[i];
back(1);
//cout<<"nr de solutii:"<<nrsol;
return 0;
}
28. Se citesc două cifre diferite c1 și c2 (nenule). Afișați în ordine crescătoare toate numerele care conțin exact c1 cifre
egale cu c2 și c2 cifre egale cu c1.
#include<bits/stdc++.h>
using namespace std;

int st[100],c1,c2,n;

void afisare(int k)
{
for(int i=1;i<=k;i++)
cout<<st[i];
cout<<'\n';
}

int valid(int k)
{
int c11=0, c22=0;
for(int i=1;i<=k;i++)
{if (st[i]==c1) c11++;
else c22++;}
if(c11>c2 || c22>c1) return 0;

return 1;
}

void back(int k)
{
for(int i=c1;i<=c2;i++)
{
st[k]=i;
if(valid(k)==1)
if (k==n)
afisare(k);
else back(k+1);
}
}

int main()
{
cin>>c1>>c2;
if(c1 > c2) swap(c1 , c2);
n=c1+c2;
back(1);

return 0;
}
29. Fie n un număr natural nenul, mulțimea A={1,2,3,...,n} și un număr m, 1 ≤ m ≤ n. Să se determine toate partițiile
disjuncte ale mulțimii A, formate din exact m submulțimi.
O partiție a mulțimii A este formată din k (1 ≤ k ≤ n) submulțimi disjuncte ale lui A: A1, A2, …, Ak cu proprietatea
că A=A1U A2 U...U Ak. (Partitii multime)
#include <bits/stdc++.h>
using namespace std;

ifstream fin("pm.in");
ofstream fout("pm.out");

int x[10], n , m;

int maxim(int k)
{
int maxi = 0;
for(int i = 1 ; i <= k ; i++)
maxi = max(x[i] , maxi);
return maxi;
}
void afisare()
{
int maxi = maxim(n);
if(maxi == m)
{
for(int i = 1 ; i <= maxi ; i++)
{
for(int j = 1 ; j <= n ; j++)
if(x[j] == i) fout << j;
fout << "*";
}
fout << '\n';
}
}

void back(int k)
{
for(int i = 1 ; i <= maxim(k - 1)+1 ; i++)
{
x[k] = i;
if(k == n) afisare();
else back(k + 1);
}
}

int main()
{
fin >> n >> m;
x[1] = 1;
back(2);
return 0;
}
30. Se citește un număr natural n. Afișați în ordine lexicografică toate submulțimile mulțimii {1, 2, ..., n} care sunt
formate dintr-un număr impar de elemente.
#include <bits/stdc++.h>
using namespace std;

int n , x[50];

void afisare(int k)
{
for(int i = 1 ; i <= k ; i++)
cout << x[i] << " ";
cout << '\n';
}
void back(int k)
{
for(int i = x[k - 1] + 1 ; i <= n ; i++)
{
x[k] = i;
if(k % 2 == 1) afisare(k);
back(k + 1);
}
}

int main()
{
cin >> n;
back(1);
}
31. Se citesc un număr natural n având cifrele diferite două câte două și o cifră c. Afișați în ordine descrescătoare
numerele formate din c cifre distincte care se pot obține din cifrele lui n și care au cifrele ordonate crescător.
#include<bits/stdc++.h>
using namespace std;
int n,c,st[100],j,v[100];
void afisare(int k)
{
for(int i=1;i<=k;i++)
cout<<st[i];
cout<<endl;
}
int valid(int k)
{ if (st[1]==0) return 0;
if(k>=2 && st[k]<=st[k-1])
return 0;
return 1;
}
void back(int k)
{
for(int i=1;i<=j;i++)
{
st[k]=v[i];
if(valid(k)==1)
{ if(k==c)
afisare(k);
else
back(k+1);
}
}
}
int main()
{
j=0;
cin>>n>>c;
while(n!=0)
{
v[++j]=n%10;
n=n/10;
}
for(int i=1;i<j;i++)
for(int z=i+1;z<=j;z++)
if(v[i]<v[z])
swap(v[i],v[z]);
back(1);
return 0;
}
32. Se dă un număr natural n. Determinaţi, în ordine lexicografică, toate modalităţile de a-l scrie pe n ca sumă de numere
naturale distincte.
#include <bits/stdc++.h>
using namespace std;
ifstream fin("partitiinumar1.in");
ofstream fout("partitiinumar1.out");
int st[100],n,nrsol,s;
void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{

for(int i=1;i<k;i++)
{

if (st[k]==st[i])
return 0;
if(st[k]<st[k-1])
return 0;
}
return 1;
}

void back(int k, int s)


{
for(int i=1;i<=n;i++)
{
st[k]=i;
if(valid(k) == 1)
{
s=s+st[k];
if(s <= n)
{
if (s==n)
afisare(k);
else back(k+1,s);
}
s=s-st[k];
}

}
}
int main()
{ fin>>n;
back(1,0);
//fout<<"nr de solutii:"<<nrsol;
return 0;
}
33. Se dă un număr natural n. Determinați, în ordine lexicografică, toate modalitățile de a-l scrie pe n ca sumă de numere
naturale pare.
#include <bits/stdc++.h>
using namespace std;
int st[100],n,nrsol,s;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<'\n';
}

int valid(int k)
{

if(st[k]<st[k-1])
return 0;
if (st[k]%2==1)
return 0;

return 1;
}

void back(int k, int s)


{
for(int i=1;i<=n;i++)
{
st[k]=i;
if(valid(k) == 1)
{
s=s+st[k];
if(s <= n)
{
if (s==n)
afisare(k);
else back(k+1,s);
}
s=s-st[k];
}
}
}
int main()
{ cin>>n;
back(1,0);
if(nrsol==0) cout<<"imposibil";
return 0;
}
34. Se dă un număr natural n. Determinați, în ordine lexicografică, toate modalitățile de a-l scrie pe n ca sumă de numere
naturale impare distincte.
#include <bits/stdc++.h>
using namespace std;
int st[100],n,nrsol,s;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<'\n';
}

int valid(int k)
{

if(st[k-1]==st[k])
return 0;
if(st[k]<st[k-1])
return 0;
if (st[k]%2==0)
return 0;

return 1;
}

void back(int k, int s)


{
for(int i=1;i<=n;i++)
{
st[k]=i;
if(valid(k) == 1)
{
s=s+st[k];
if(s <= n)
{
if (s==n)
afisare(k);
else back(k+1,s);
}
s=s-st[k];
}

}
}
int main()
{ cin>>n;
back(1,0);
if(nrsol==0) cout<<"imposibil";
return 0;
}
35. Se consideră n tipuri de bancnote, cu valorile v[1] v[2] ... v[n], ordonate strict crescător. Pentru fiecare tip de bancnote
se știe numărul de bancnote disponibile c[1] c[2] ... c[n]. Se cere să se determine o modalitate de a plăti integral o sumă
dată S cu bancnotele disponibile, astfel încât să se folosească cel puțin o bancnotă de fiecare tip. (Programul va afișa pe
ecran n numere, reprezentând o modalitate de plată a sumei S. Fiecare număr x[i] va reprezenta numărul de bancnote de
valoarea x[i] folosite pentru plata sumei S.)
#include <bits/stdc++.h>

using namespace std;

int n , p[20] , x[11] , a[20] , maxi , ok , s , c[20];

void afisare()
{
for(int i = 1 ; i <= n ; i++)
cout << x[i] << " ";
ok = 1;
}

void back(int k , int sp)


{
for(int i = 1 ; i <= c[k] && !ok; i++)
{
x[k] = i;
sp += x[k] * a[k];

if(k == n && sp == s) afisare();


else back(k + 1 , sp);

sp -= x[k] * a[k];
}
}

int main()
{
cin >> n >> s;
for(int i = 1 ; i <= n ; i++)
cin >> a[i];
for(int i = 1 ; i <= n ; i++)
cin >> c[i];
back(1 , 0);
}
36. Se consideră n tipuri de bancnote, cu valorile v[1] v[2] ... v[n], ordonate strict crescător. Se cere să se determine o
modalitate de a plăti integral o sumă dată S cu bancnotele disponibile, știind că se pot folosi oricâte bancnote de orice tip.
#include <bits/stdc++.h>
using namespace std;

int n , x[1001] , v[1001] , ok , s;

void afisare()
{
for(int i = 1 ; i <= n ; i++)
cout << x[i] << " ";
ok = 1;
}

void back(int k , int sp)


{
for(int i = 0 ; i <= (s - sp) / v[k] && !ok ; i++)
{
x[k] = i;
sp += x[k] * v[k];
if(sp <= s)
if(k == n)
{
if(sp == s) afisare();
}
else back(k + 1 , sp);
sp -= x[k] * v[k];
}
}

int main()
{
cin >> n >> s;
for(int i = 1 ; i <= n ; i++)
cin >> v[i];

back(1 , 0);
}
37. Se dă un număr natural nenul n. Să se determine toate modalităţile distincte de descompunere a numărului n în sumă
de 3 şi 5.
#include <bits/stdc++.h>
using namespace std;

ifstream fin("suma35.in");
ofstream fout("suma35.out");

int n , x[1002];

void afisare(int k)
{
for(int i = 1 ; i <= k ; i++)
fout << x[i] << " ";
fout << '\n';
}
void back(int k , int sp)
{
for(int i = x[k - 1]; i <= 5; i += 2)
{
x[k] = i;
sp += x[k];
if(sp <= n)
if(sp == n) afisare(k);
else back(k + 1 , sp);
sp -= x[k];
}
}

int main()
{
fin >> n;
x[0] = 3;
back(1 , 0);
}
38. Dându-se un număr natural nenul S, să se afișeze în ordine crescătoare toate numerele naturale cu cifre distincte care
au suma cifrelor egală cu S.

39. Se dă un număr natural n şi un interval [a,b]. Determinaţi, în ordine lexicografică, toate modalităţile de a-l scrie
pe n ca sumă de numere naturale din intervalul [a,b].
#include <bits/stdc++.h>
using namespace std;
ifstream fin("partitiinumar3.in");
ofstream fout("partitiinumar3.out");
int st[100],n,nrsol,s,a,b;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{

if(k>=2 && st[k]<st[k-1]) //fara for ca sa fie elemente distincte


return 0;

return 1;
}

void back(int k, int s)


{
for(int i=a;i<=b;i++)
{
st[k]=i;
if(valid(k) == 1)
{
s=s+st[k];
if(s <= n)
{
if (s==n)
afisare(k);
else back(k+1,s);
}
s=s-st[k];
}

}
}
int main()
{ fin>>n>>a>>b;
back(1,0);
//fout<<"nr de solutii:"<<nrsol;
return 0;
}
40. Se dă un număr natural n şi o mulţime cu m elemente, numere naturale nenule. Determinaţi, în ordine lexicografică,
toate modalităţile de a-l scrie pe n ca sumă de termeni din acea mulţime.
#include <bits/stdc++.h>
using namespace std;
ifstream fin("partitiinumar4.in");
ofstream fout("partitiinumar4.out");
int st[100],n,nrsol,s,p,m,v[100];

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
fout<<st[i]<<" ";
fout<<endl;
}

int valid(int k)
{
if(k>=2 && st[k]<st[k-1])
return 0;
return 1;
}

void back(int k, int s)


{
for(int i=1;i<=m;i++)
{
st[k]=v[i];
if(valid(k) == 1)
{
s=s+st[k];
if(s <= n)
{
if (s==n)
afisare(k);
else back(k+1,s);
}
s=s-st[k];
}

}
}
int main()
{
fin>>n>>m;
for(int i=1;i<=m; i++)
fin>>v[i];
sort(v+1,v+m+1);
back(1,0);
//fout<<"nr de solutii:"<<nrsol;
return 0;
}
41. Se citește n număr natural nenul. Afișați în ordine crescătoare toate numerele care au o cifră egală cu 1, două cifre
de 2, …, n cifre egale cu n.
#include <iostream>
using namespace std;

int n,X[12],F[5],m;

void afisare()
{
for(int i=1;i<=m;i++)
cout<<X[i];
cout<<"\n";
}

void back(int k)
{
for(int i=1;i<=n;i++)
if(F[i])
{
X[k]=i;
F[i]--;
if(k==m) afisare();
else back(k+1);
F[i]++;
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
F[i]=i;
m=n*(n+1)/2;
back(1);
return 0;
}
42. Permutari de n elemente din multimea {1,2,...,n}
intra n elemente => ies n elemente distincte
(orice solutie are toate numerele de la 1 la n)
#include <iostream>
using namespace std;
int st[100],n,nrsol;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0; //daca se repeta numere nu e valid
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n;
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}
43. Permutarile a n elemente dintr-o multime citita; elementele sale
se retin intr-un vector.
(multime=set de elemente distincte)
#include <iostream>
using namespace std;
int st[100],v[100],n,nrsol;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<v[st[i]]<<" ";
cout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0; //daca se repeta numere nu e valid
if (k>=2 && v[st[k]]<0 && v[st[k-1]]<0)
return 0;
return 1; //e valid
}

void back(int k)
{ for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n;
for(int i=1;i<=n;i++)
cin>>v[i];
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}

44. Aranjamente de n elemente din multimea {1,2,...,n} luate cate m cu n>=m.


#include <iostream>
using namespace std;
int st[100],n,m,nrsol;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

int valid(int k)
{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
if (st[k]==st[i])
return 0; //daca se repeta numere nu e valid
return 1; //e valid
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n>>m;
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}
45. Combinari de n elemente din multimea {1,2,...,n} luate cate m cu n>=m.
ex pt n=3 si m=2
#include <iostream>
using namespace std;
int st[100],n,m,nrsol;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

//int valid(int k)
//{ for(int i=1;i<k;i++) //compar elementul de pe niv k cu cele deja existente
// if (st[k]==st[i])
// return 0; //daca se repeta numere nu e valid
/// if (k>=2 && st[k]<st[k-1]) return 0; //sa fie in ordine crescatoare
// return 1; //e valid
//}

//alta varianta in vare am combinat cele doua conditii


int valid(int k)
{
if (k>=2 && st[k]<=st[k-1]) return 0; //sa fie in ordine crescatoare
return 1; //e valid
}
void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if(valid(k)==1) //daca valoarea e valida
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n>>m;
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}
alta varianta de combinari, fara a folosi valid

#include <iostream>
using namespace std;
int st[100],n,m,nrsol;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

void back(int k)
{
for(int i=st[k-1]+1;i<=n-m;i++) //pe fiecare nivel pornesc de la valoarea anterioara +1
{ st[k]=i; //am asigurat ca sunt in ordine crescatoare
if (k==m)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n>>m;
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}

46. Se da o multime de n elemente {1,2,...,n}; sa se afiseze toate submultimile sale.


Combinari (in solutie se afla in ordine crescatoare)<=>submultime
#include <iostream>
using namespace std;
int st[100],n,nrsol;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

void back(int k)
{
for(int i=st[k-1]+1;i<=n;i++) //pe fiecare nivel pornesc de la valoarea anterioara +1
{ st[k]=i; //am asigurat ca sunt in ordine crescatoare
afisare(k);
back(k+1); //completez soutia anterioara
}//daca nu e valida continua for-ul (creste i)
}
int main()
{ cin>>n;
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}
47. Se citeste o multime de n elemente; sa se afiseze toate submultimile sale.
Combinari (in solutie se afla in ordine crescatoare)<=>submultime
#include <iostream>
using namespace std;
int st[100],v[100],n,nrsol;

void afisare(int k)
{
nrsol++;
cout<<"{";
for(int i=1;i<=k-1;i++)
cout<<v[st[i]]<<",";
cout<<v[st[k]]<<"} ";
cout<<endl;
}

void back(int k)
{
for(int i=st[k-1]+1;i<=n;i++) //pe fiecare nivel pornesc de la valoarea anterioara +1
{ st[k]=i; //am asigurat ca sunt in ordine crescatoare
afisare(k);
back(k+1); //completez soutia anterioara
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n;
for(int i=1;i<=n;i++)
cin>>v[i];
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}

48. Produsul cartezian a n multimi cu n elemente fiecare {1,2,3,...,n}


!!!Se pot repeta valori in solutie: validul ar returna 1 permanent
Intra n elemente, ies n elemente care se pot repeta.
#include <iostream>
using namespace std;
int st[100],n,nrsol;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

void back(int k)
{
for(int i=1;i<=n;i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n;
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}

49. Produsul cartezian a n multimi cu v[k] elemente fiecare.


Se citeste un vector cu n elemente care contine pe pozitia k
numarul de elemente de pe nivelul k
!!!Se pot repeta valori in solutie: validul ar returna 1 permanent
Intra n elemente, ies n elemente care se pot repeta.
#include <iostream>
using namespace std;
int st[100],v[100],n,nrsol;

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<st[i]<<" ";
cout<<endl;
}

void back(int k)
{
for(int i=1;i<=v[k];i++) //pun pe fiecare nivel valori de la 1 la n
{ st[k]=i;
if (k==n)//am solutie
afisare(k);
else back(k+1); //cresc k, construiesc noul nivel
}//daca nu e valida continua for-u; (creste i)
}
int main()
{ cin>>n;
for(int i=1;i<=n;i++)
cin>>v[i];
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}

50. se considera multimea de litere {a,b,c,d,e}. Se formeaza cuvinte de cate 4 litere


din mt data a.i. sa nu fie doua vocale alaturate si sa aiba cel putin o vocala.
numarati cate cuvinte incep cu a si se termina cu e.
Intr-un cuvant se pot repeta litere.

#include <iostream>
using namespace std;
int st[100],n,nrsol;
char v[100]=" abcde";

void afisare(int k)
{ if (st[1]==1 && st[4]==5) { nrsol++;
for(int i=1;i<=k;i++)
cout<<v[st[i]];
cout<<endl;
}
}

int valid (int k)


{
if (k>=2 && st[k]==1 && st[k-1]==5) return 0; //am ae
if (k>=2 && st[k]==5 && st[k-1]==1) return 0; //am ea
if (k>=2 && st[k]==1 && st[k-1]==1) return 0;
if (k>=2 && st[k]==5 && st[k-1]==5) return 0;
int z=0;
for(int i=1;i<=k;i++)
if (st[i]==1 || st[i]==5) z++;
if (k==4 && z==0) return 0;
return 1;
}
void back(int k)
{
for(int i=1;i<=5;i++)
{ st[k]=i;
if (valid(k))
if (k==4)
afisare(k);
else back(k+1);
}
}
int main()
{
back(1);
cout<<"nr de solutii care incep cu a si se termina cu e:"<<nrsol;
return 0;
}
51. Un gradinar are la dispozitie 5 tipuri de legume
(rosii, dovlecei, castraveti, ardei, cartofi) pe care trebuie sa ii planteze.
Stiind ca nu are voie sa planteze dovlecei langa rosii si castraveti langa ardei
sa se afiseze toate posibilitatile de a planta cele 5 tipuri de legume.
primele solutii generate sunt
rosii, castraveti, dovlecei, ardei, cartofi
rosii, castraveti, dovlecei, cartofi, ardei
rosii, castraveti, cartofi, dovlecei, ardei
rosii, castraveti, cartofi, ardei, dovlecei
..
cartofi, ardei, dovlecei, castraveti, rosii

#include <iostream>
using namespace std;
int st[10],n,nrsol;
char v[][12]={"","rosii", "dovlecei", "castraveti", "ardei", "cartofi"};

void afisare(int k)
{ nrsol++;
for(int i=1;i<=k;i++)
cout<<v[st[i]]<<", ";
cout<<endl;
}
int valid (int k)
{
if (k>=2 && st[k]==1 && st[k-1]==2) return 0;
if (k>=2 && st[k]==2 && st[k-1]==1) return 0;
if (k>=2 && st[k]==3 && st[k-1]==4) return 0;
if (k>=2 && st[k]==4 && st[k-1]==3) return 0;
for(int i=1;i<k;i++)
if (st[k]==st[i]) return 0;
return 1;
}
void back(int k)
{
for(int i=1;i<=5;i++)
{ st[k]=i;
if (valid(k))
if (k==5)
afisare(k);
else back(k+1);
}
}
int main()
{
back(1);
cout<<"nr de solutii:"<<nrsol;
return 0;
}
Backtracking in plan

1. Saritura calului:
Cerinţa
Se consideră o tablă de şah cu n linii şi m coloane. La o poziţie dată se află un cal de şah, acesta putându-se deplasa pe
tablă în modul specific acestei piese de şah (în L).

Să se determine o modalitate de parcurgere integrală a tablei de către calul dat, astfel încât acesta să nu treacă de două ori
prin aceeaşi poziţie.

Date de intrare
Programul citește de la tastatură numerele n şi m , apoi numere x y, reprezentând dimensiunile tablei (numărul de linii şi
numărul de coloane) , respectiv coordonatele iniţiale ale calului (linie, coloana).

Date de ieşire
Programul afișează n linii cu câte m numere naturale cuprinse între 1 și n*m, separate prin exact un spațiu, reprezentând
parcurgerea solicitată.

Problema:
#include <bits/stdc++.h>
using namespace std;

int n , m , is , js , ib , jb , a[7][7] , cnt;

int dic[] = {-2 , -1 , 1 , 2 , 2 , 1 , -1 , -2};


int djc[] = { 1 , 2 , 2 , 1 , -1 , -2 , -2 , -1};

int inside(int i , int j)


{
if( i >= 1 && i <= n && j >= 1 && j <= m) return 1;
return 0;
}

void afis()
{
for(int i = 1 ; i <= n ; i++)
{
for(int j = 1 ; j <= m ; j++)
cout << a[i][j] << " ";
cout << '\n';
}
}

void back(int i , int j , int pas)


{
for(int d = 0 ; d < 8 ; d++)
{
int inou = i + dic[d];
int jnou = j + djc[d];
if(inside(inou , jnou) && a[inou][jnou] == 0)
{
a[inou][jnou] = pas;
if(pas == n * m)
{
afis();
exit(0);
}
else back(inou , jnou , pas + 1);
a[inou][jnou] = 0;
}
}
}
int main()
{
cin >> n >> m;
cin >> is >> js;
a[is][js] = 1;
back(is , js , 2);
return 0;
}

2. La curtea regelui Arthur s-au adunat n cavaleri numerotati de la 1 la n.


Despre ei se cunosc relatii de dusmanie de forma (x,y) cu semnificati ca x si y se dusmanesc.
Afisati toate modurile in care Arthur ii poate aranja la o masa rotunda cu n scaune astfel incat sa nu stea unul langa altul 2
cavaleri care dusmanesc.
de exemplu, pentru date.in
5
12
14
25
34
solutiile
13245
15423
23154
24513
31542
32451
42315
45132
51324
54231

Problema:
#include <fstream>
#include <iostream>
using namespace std;
ifstream fin("date.in");

int a[50][50],x[50],p[50],n;

void citire()
{
int i,j;
fin>>n;
while(fin>>i>>j)
a[i][j]=a[j][i]=1; //pereche de certati

void afisare()
{
int i;
for(i=1;i<=n;i++)
cout<<x[i]<<" ";
cout<<endl;
}

int valid(int k)
{
if(k>1)
if(a[x[k]][x[k-1]]==1) return 0;
if(k==n)
if(a[x[1]][x[n]]==1) return 0;
return 1;
}

void back(int k)
{
for(int i=1;i<=n;i++)
if(p[i]==0) //iau i daca p[i]==0
{
x[k]=i;
p[i]=1; //marchez ca am trecut prin i
if(valid(k))
if(k==n) afisare();
else back(k+1);
p[i]=0; //refac 0 vizitatul lui i
}

}
int main()
{
citire();
back(1);
return 0;
}

3. Se considera o harta cu n tari, unele dintre ele fiind vecine; sa se determine un mod de colorare a hartii folosind exact 4
culori A,B,C,D a.i. doua tari vecine sa nu fie colorate la fel.
//se retine 1 daca doua tari sunt vecine, sau 0 iin caz contrar

Problema:
#include <fstream>
#include <iostream>
using namespace std;
ifstream fin("date.in");

int a[50][50],x[50],p[50],n,ok=0;

void citire()
{
int i,j;
fin>>n;
while(fin>>i>>j)
a[i][j]=a[j][i]=1; //pereche de tari vecine

void afisare()
{
int i;
ok=1;
for(i=1;i<=n;i++)
if (x[i]==1) cout<<"A ";
else if (x[i]==2) cout<<"B ";
else if (x[i]==3) cout<<"C ";
else if (x[i]==4) cout<<"D ";
cout<<endl;
}

int valid(int k)
{
for(int i=1;i<k;i++)
if(a[x[k]][x[i]]==1 && x[k]==x[i]) return 0;
return 1;
}

void back(int k)
{
for(int i=1;i<=n && ok==0;i++)
if(p[i]==0) //iau i daca p[i]==0
{
x[k]=i;
p[i]=1; //marchez ca am trecut prin i
if(valid(k))
if(k==n) afisare();
else back(k+1);
p[i]=0; //refac 0 vizitatul lui i
}
}
int main()
{
citire();
back(1);
return 0;
}
4. /*Se citeste o matrice care contine numai valorile 0 si 1. Matricea
reprezinta un cer albastru, fara nori, codificat prin 0 pe care
sunt niste avioane codificate cu 1.Numarati cate avioane sunt pe cer.
(problema numararii obiectelor dintr-o fotografie)
Deplasarea in cadrul matricei se face pe cele 4 directii (N,S,E,V)
doua valori de 1 sunt considerate ca facand parte din acelasi obiect
daca sunt vecine pe orizontala sau verticala (NU pe diagonala).

011001
010110
000100
111000
001011
=> 5 obiecte : cand gasesc un obiect (o valoare 1) schimb in 0 toti vecinii sai
*/
Problema:
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("matrice.in");
void citire(int A[][101], int n, int m, int i, int j)
{
    if(i<=n)
  {
        fin>>A[i][j];
        if(j<m) citire(A,n,m,i,j+1);
        else citire(A,n,m,i+1,1); //pe linie noua j deine 1
  }
}

void afisare(int A[][101], int n, int m, int i, int j)


{
    if(i<=n)
  {
        cout<<A[i][j]<<" ";
        if(j<m) afisare(A,n,m,i,j+1);
        else
    {
            cout<<endl; //inainte de a trece la linie noua pun endl
            afisare(A,n,m,i+1,1);
    }
  }
}

void colorare(int A[][101], int n, int m, int i, int j)


{
    if (i>=1 && i<=n && j>=1 && j<=m && A[i][j]==1)
     {
         A[i][j]=0; //inlocuiesc cu 0
         colorare(A,n,m,i-1,j); //merg in vecinii lui A[i][j]
         colorare(A,n,m,i+1,j);
         colorare(A,n,m,i,j-1);
         colorare(A,n,m,i,j+1);
     }
}

void numarare(int A[][101], int n, int m, int i, int j,int &k)


{
    if(i<=n)
  {
        if(A[i][j]==1)
           {
               k++;
               colorare(A,n,m,i,j);
           }
        if(j<m) numarare(A,n,m,i,j+1,k);
        else numarare(A,n,m,i+1,1,k); //pe linie noua j deine 1
  }
}

int main()
{
    int A[101][101],n,m,k=0;
    fin>>n>>m;
    citire(A,n,m,1,1);
    afisare(A,n,m,1,1);
    numarare(A,n,m,1,1,k);
    cout<<"nr de obiecte "<<k;
    return 0;
}

5. Cerinţa
Se dă o tablă dreptunghiulară formată din n linii și m coloane, definind n*m zone, unele dintre ele fiind libere,
altele conținând obstacole. În zona aflată la poziția is, js se află un șoarece care se poate deplasa pe tablă
trecând din zona curentă în zona învecinată cu aceasta pe linie sau pe coloană. Scopul sau este să ajungă la o
bucată de brânză aflată în zona de la poziția ib, jb, fără a părăsi tabla, fără a trece prin zone care conțin
obstacole și fără a trece de două ori prin aceeași zonă.

Determinați câte modalități prin care șoarecele poate ajunge de la poziția inițială la cea a bucății de brânză
există.

Date de intrare
Fişierul de intrare soarece.in conţine pe prima linie numerele n m, separate printr-un spațiu. Următoarele n linii
conțin câte m valori 0 sau 1, separate prin exact un spațiu, care descriu tabla – valoarea 0 reprezintă o zonă
liberă, valoarea 1 reprezintă o zonă ocupată cu un obstacol. Pe linia n+2 se află 4 numere separate prin exact
un spațiu, reprezentând is js ib jb.
Date de ieşire
Fişierul de ieşire soarece.out va conţine pe prima linie numărul S, reprezentând numărul de modalități prin care
șoarecele poate ajunge de la poziția inițială la cea a bucății de brânză.

Problema:
#include <fstream>
using namespace std;
ifstream cin("soarece.in");
ofstream cout("soarece.out");
int a[20][20];
int id[]={1,-1,0,0},jd[]={0,0,1,-1},is,js,ib,jb,n,m,nr_sol;

void back(int k,int ip,int jp)


{
for(int i=0;i<4;i++) //deplasari pe 4 directii
{
int ix=ip+id[i],jx=jp+jd[i]; //calculez noile coordonate
if(!(ix<1 || ix>n || jx<1 || jx>m)) //verific sa nu iasa in matrice
if(a[ix][jx]==0) //poate sa mearga doar prin 0
{
a[ix][jx]=1; //marchez cu 1, sa nu mai treaca
if(ix==ib && jx==jb) //daca a ajuns la branzoi are solutie
++nr_sol;
else
back(k+1,ix,jx); //nu e solutie, trecem mai departe
a[ix][jx]=0; // reface 0 punctul din matrice
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
cin>>is>>js>>ib>>jb;
a[is][js]=1;//pasul 1 in punctul de plecare
back(1,is,js);
cout<<nr_sol;
return 0;
}

6. Cerința
Se dă o tablă de șah formată din n linii și m coloane, definind n*m zone, unele dintre ele fiind libere, altele conținând
obstacole. În zona de coordonate 1 1 se află un cal care se poate deplasa pe tablă în L, ca la șah, fără a părăsi tabla, fără a
trece prin zone care conțin obstacole și fără a trece de două ori prin aceeași zonă.

Determinați o modalitate prin care calul poate ajunge în zona de coordonate n m – unde se află o căpiță de fân.

Date de intrare
Fişierul de intrare traseucal.in conţine pe prima linie numerele n m, separate printr-un spațiu. Următoarele n linii conțin
câte m valori, care descriu tabla: 0 corespunde unei zone libere, caracterul 1 corespunde unei zone ocupate de un obstacol.
Date de ieşire
Fişierul de ieşire traseucal.out va conţine n linii, pe fiecare linie fiind câte m numere, care descriu traseul calului, astfel:

zonelor prin care nu va trece calul le corespund valoarea 0.


zonei în care se află inițial calul îi corespunde valoarea 1
următoarei zone din traseul calului îi corespunde valoarea 2
fiecărei zone din traseul calului îi corespunde o valoare număr natural semnificând la al câtelea pas ajunge calul în acea
zonă.
Numerele de pe fiecare linie fișierului de ieșire sunt separate prin exact un spațiu.

Exemplu:
traseucal.in

45
00100
00100
00000
00010
traseucal.out

14000
00030
02500
00006

Problema:
#include<fstream>
using namespace std;
const int dx[8]={-1,1,2,2,1,-1,-2,-2};
const int dy[8]={2,2,1,-1,-2,-2,-1,1};
int n,m,t[25][25],nrsol,xin,yin;
ifstream fin("traseucal.in");
ofstream fout("traseucal.out");

void citire()
{int i,j;
fin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
fin>>t[i][j];
}

void afisare()
{ int i,j;
nrsol++; //cresc numarul de solutii
for(i=1;i<=n;i++)
{ for(j=1;j<=m;j++)
fout<<t[i][j]<<" ";
fout<<endl;
}
fout<<endl;
}

void back(int lin,int col,int k)


{
int inou,jnou,i;
for(i=0;i<8;i++) //se poate deplasa pe 4 directii
{ inou=lin+dx[i]; //calculam noile coordonate
jnou=col+dy[i];
if( inou>=1 && inou<=n && jnou>=1 && jnou<=m)
if (inou==n && jnou==m && t[inou][jnou]==0)
{ t[inou][jnou]=k+1;
afisare();
exit(0);
t[inou][jnou]=0; //reinitializez cu 0 pozitia inou,jnou
}
else //nu a ajuns la linia n coloana m
if (t[inou][jnou]==0)
{ t[inou][jnou]=k+1; //daca e o pozitie valida, o completez
back(inou,jnou,k+1); //plec mai departe
t[inou][jnou]=0; //la revenirea din recursivitate coboara un nivel
}
}
}

int main()
{ citire();
t[1][1]=1;
back(1,1,1);
fout.close();
return 0;
}

7. Cerința
Hercule trebuie sa strabată un labirint cu capcane reprezentat de o matrice cu n linii și m coloane. Pentru fiecare celula a
labirintului, se cunoaște timpul exprimat în minute după care celula respectivă devine capcană. După ce o celula devine
capcana, Hercule piere dacă intră în acea celulă. Initial Hercule se află în celula de coordonate (1, 1) și trebuie să ajungă în
celula de cordonate (n,m).

Sa se afișeze numarul total de drumuri pe care le poate urma Hercule prin labirint, astfel încât Hercule să nu piară.

Date de intrare
Fișierul de intrare hercule.in conține pe prima linie numerele n m, iar pe următoarele n linii câte m valori naturale.

Date de ieșire
Fișierul de ieșire hercule.out va conține pe prima linie numărul total de drumuri prin care Hercule poate ajunge în celula
destinație.

Exemplu:
hercule.in
45
41181
63451
32888
13429
hercule.out
2

Problema:
#include <iomanip>
#include <fstream>
using namespace std;
ifstream fin("hercule.in");
ofstream fout("hercule.out");

int n, m, a[25][25], b[25][25], nrsol = 0;

const int di[]={0,0,1,-1}, dj[]={1,-1,0,0};

void back(int i, int j, int pas)


{
if(i >= 1 && i <= n && j >= 1 && j <= m && pas <= a[i][j] && b[i][j] == 0)
{
b[i][j] = pas;
if(i == n && j == m)
nrsol++;
else
for(int k = 0 ; k < 4 ; ++k)
back(i + di[k], j + dj[k], pas + 1);
b[i][j] = 0;
}
}

int main()
{
fin >> n >> m;
for(int i = 1 ; i <= n ; ++i)
for(int j = 1 ; j <= m ; ++j)
fin >> a[i][j];
back(1, 1, 1);
fout << nrsol;
return 0;
}

8. Cerința
Se consideră o tablă de șah de dimensiune n. Să se plaseze pe tablă n regine astfel încât să nu existe două regine care să se
atace.

Date de intrare
Programul citește de la tastatură numărul n.

Date de ieșire
Programul va afișa pe ecran o singură configurație validă a tablei de șah. Ea va fi alcătuită din n linii cu câte n caractere -
sau *, separate prin câte un spațiu. Caracterul - reprezintă o poziție liberă de pe tablă, iar caracterul * reprezintă o poziție
de pe tablă ocupată de o regină.

Restricții și precizări
4 ≤ n ≤ 10;
două regine se atacă dacă se află pe aceeași linie, aceeași coloană sau aceeași diagonală;
orice configurație validă a tablei este acceptată.
Exemplu:
Intrare

4
Ieșire

--*-
*---
---*
-*--

Problema:
#include<iostream>
#include<cmath>
using namespace std;
int n,st[100],nrsol=0;

void afisare(int k)
{
int i,j;
nrsol++;
for(i=1;i<=k;i++)
{
for(j=1;j<=k;j++)
if (st[i]==j) cout<<" * ";
else cout<<" - ";
cout<<endl;
}
cout<<endl;
}
int valid(int k)
{
for(int i=1;i<k;i++)
{
if (st[i]==st[k]) return 0;
if (fabs(st[k]-st[i])==fabs(k-i)) return 0;
}
return 1;
}

void back(int k)
{
for(int i=1;i<=n && nrsol==0;i++)
{
st[k]=i;
if (valid(k))
if (k==n) afisare(k);
else back(k+1);
}
}

int main()
{ cin>>n;
back(1);
}

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