Sunteți pe pagina 1din 19

METODA GREEDY

1. Se citesc 3 numere naturale S, n si e cu urmatoarele semnificatii: S este o suma de bani care


trebuie platita folosind bancnote care au valori puterile lui e de la 1 la e la n. Se se afiseze modalitatea
de plata folosind un numar minim de bancnote de tipurile precizate. Sa se afiseze la final numarul de
bancnote folosite. Datele se vor citi din fisierul eur.in, iar rezultatele se vor afisa in fisierul eur.out.

Exemplu: 
eur.in 
444 5 2 
eur.out 
13 bancnote de valoarea 32 
1 bancnote de valoarea 16 
1 bancnote de valoarea 8 
1 bancnote de valoarea 4 
16 
Explicatie: n=5, e=2 rezulta ca bancotele au valorile 1, 2, 4, 8, 16 si 32. 

REZOLVARE :

#include <fstream>

using namespace std;

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

int main()
{
int S,n,e,t=0;

fin>>S>>n>>e;

int p=1,k=0;

while(p*e<=S && k<n) //calc. bancota maxima (<=S avand cel mult valoarea e la n)
{
p=p*e;
k++;
}
while(S>0)
{
if(S>=p) fout<<S/p<<"bancnote de valoarea"<<p<<endl; //bancnotele de valoare p

t=t+S/p; //numar bancnotele folosite

S=S%p; //cat mai ramane de platit

p=p/e; //bancnota urmatoare ca valoare (mai mica)


}

fout<<t;

return 0;
}
2. Problema rucsacului (cazul continuu) 
O persoana are un rucsac cu care poate transporta o greutate maxima g. Persoana are la dispozitie n
obiecte pentru care stie greutatea si castigul obtinut daca transporta obiectul. 
Fiecare obiect poate fi transportat integral sau taiat. 
Sa se precizeze ce obiecte alege persoana si in ce proportie le ia astfel incat castigul total sa fie maxim
si sa nu se depaseasca greutatea maxima a rucsacului. 
Exemplu: 
g=3 n=3 
obiectele(greutate,castig): 
2 2 
1 4 
3 6 
Solutie(greutate, castig, raport taiere): 
1,4,1 
3,6,0.6667 (al doilea obiect se ia in raport de 2/3) 
castig maxim=8 

REZOLVARE :

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

struct obiect
{
float g,c,r; //greutate, castig, raportul cat se ia din obiect
};

void citire(float &g, int &n, obiect a[])


{
fin>>g>>n;
for(int i=1;i<=n;i++)
{ fin>>a[i].g>>a[i].c;
a[i].r=0; //initial nu se foloseste obiectul
}
}

void ordonare(int n, obiect a[]) //ordonare dupa castig/greutate


{
int i,j;
obiect aux;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
if(a[i].c/a[i].g<a[j].c/a[j].g)
{
aux=a[i]; a[i]=a[j]; a[j]=aux;
}
}

void afisare(int n, obiect a[])


{
float c=0;
for(int i=1;i<=n;i++)
{ fout<<a[i].g<<","<<a[i].c<<","<<setprecision(4)<<a[i].r<<"\n";
c=c+a[i].c*a[i].r;
}
fout<<"castig maxim="<<c;
}

void greedy(float g, int n, obiect a[])


{
obiect s[100];
int i,k;
float sp=0;
k=0; i=1;
while(sp<g)
{
if(sp+a[i].g<=g)
{ sp=sp+a[i].g;
s[++k]=a[i];
s[k].r=1;//obiect intreg
}
else
{
s[++k]=a[i];
s[k].r=(g-sp)/a[i].g;//obiect fractionat
sp=g;
}
i++;
}
afisare(k,s);
}

int main()
{
int n;
obiect a[100];
float g;
citire(g,n,a);
ordonare(n,a);
greedy(g,n,a);

3. Problema programarii spectacolelor 


Intr-o sala de spectacol trebuie planificate n spectacole intr-o zi. Pentru fiecare spectacol se cunosc
ora de inceput si ora de terminare (numere intregi). 
Sa se planifice un numar maxim de spectacole astfel inct sa nu fie doua spectacole care sa se
suprapuna. 
Exemplu: 
date.in 

2 4 
8 11 
5 6 
5 8 
3 7 
7 8 
9 12 
date.out: 
2,4 5,6 7,8 9,12 
REZOLVARE :

#include<fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

struct spectacol
{
int s,d;
};

void citire(int &n, spectacol a[])


{
fin>>n;
for(int i=1;i<=n;i++)
fin>>a[i].s>>a[i].d;
}

void ordonare(int n, spectacol a[])


{
int i,j;
spectacol aux;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
if(a[i].d>a[j].d)
{
aux=a[i]; a[i]=a[j]; a[j]=aux;
}
}

void afisare(int n, spectacol a[])


{
for(int i=1;i<=n;i++)
fout<<a[i].s<<","<<a[i].d<<" ";
}

void greedy(int n, spectacol a[])


{
spectacol s[100];
int i,k;
k=1;
s[1]=a[1];
for(i=2;i<=n;i++)
if(s[k].d<a[i].s) s[++k]=a[i];
afisare(k,s);
}

int main()
{
int n;
spectacol a[100];
citire(n,a);
ordonare(n,a);
greedy(n,a);
fin.close();
fout.close();
}
DIVIDE ET IMPERA
1. Folosind metoda divide et impera, scrieti o functie care sa determine daca un tablou cu
elemente intregi este ordonat crescator. 

REZOLVARE :

int ordon(int v[], int s, int d)


{
if(s==d) return 1;
else
if(ordon(v,s,(s+d)/2) && ordon(v,(s+d)/2+1,d) && v[(s+d)/2]<=v[(s+d)/2+1])
return 1;
else return 0;
}

2. Scrieti o functie minmax care sa determine elementul minim si elementul maxim dintr-un
tablou cu elemente intregi folosind metoda divide et impera.

REZOLVARE :

void minmax(int v[], int s, int d, int &minn, int &maxx)


{
if(s==d) minn=maxx=v[s];
else
{
int a,b,x,y;
minmax(v,s,(s+d)/2,a,x);
minmax(v,(s+d)/2+1,d,b,y);
if(a<b) minn=a;
else minn=b;
if(x>y) maxx=x;
else maxx=y;
}
}

3. Se citeste un vector cu n elemente numere naturale. Sa se calculeze CMMDC al elementelor


vectorului folosind divide et impera.

REZOLVARE :

#include<iostream>

using namespace std;

int cmmdc(int a[100], int s, int d)


{ if(s==d) return a[s];
else
{ int x,y;
x=cmmdc(a,s,(s+d)/2);
y=cmmdc(a,(s+d)/2+1,d);
while(x!=y)
if(x>y) x=x-y;
else y=y-x;
return x;
}
}

int main()
{
int a[100],n,i;
cin>>n;
for(i=1;i<=n;i++) cin>>a[i];
cout<<cmmdc(a,1,n);
system("pause");
return 0;
}

4. Sortarea prin interclasare (MergeSort)

REZOLVARE :

#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

void inter(int a[50000], int s, int m, int d)


{
int i,j,k,c[50000];
i=s; j=m+1;k=1;
while(i<=m && j<=d)
if(a[i]<a[j]) c[k++]=a[i++];
else c[k++]=a[j++];
while(i<=m) c[k++]=a[i++];
while(j<=d) c[k++]=a[j++];
k=1;
for(i=s;i<=d;i++) a[i]=c[k++];
}

void msort(int a[50000], int s, int d)


{
int m;
if(s<d)
{
m=(s+d)/2;
msort(a,s,m);
msort(a,m+1,d);
inter(a,s,m,d);
}
}

void citire(int a[50000], int &n)


{
int i;
fin>>n;
for(i=1;i<=n;i++) fin>>a[i];
}

void afis(int a[50000], int n)


{
int i;
for(i=1;i<=n;i++) fout<<a[i]<<" ";
}

int main()
{
int a[50000], n;
citire(a,n);
msort(a,1,n);
afis(a,n);
return 0;}
5. Se citeste un vector cu n elemente numere naturale. Sa se calculeze suma elementelor
vectorului folosind divide et impera.
REZOLVARE :

#include<iostream>

using namespace std;

int suma(int a[100], int s, int d)


{ if(s==d) return a[s];
else return suma(a,s,(s+d)/2)+suma(a,(s+d)/2+1,d);
}

int main()
{
int a[100],n,i;
cin>>n;
for(i=1;i<=n;i++) cin>>a[i];
cout<<suma(a,1,n);
system("pause");
return 0;
}

6. Se citeste un vector cu n elemente numere naturale. Sa se determine elementul minim din


vector folosind divide et impera.
REZOLVARE :

#include<iostream>

using namespace std;

int min(int a[100],int s , int d)


{
if ( s == d ) return a[s];
else
{
int m = (s+d)/2;
int m1 = min(a,s,m);
int m2 = min(a,m+1,d);

if ( m1 < m2 ) return m1;


else return m2;

}
}

int main()
{
int a[100];
int n ;
cin>> n;
for (int i = 0 ; i < n ;i++)
cin>>a[i];

cout << min(a,1,n);

system("pause");
return 0;
}

7. Cautarea binara.
REZOLVARE :

#include<fstream>

using namespace std;


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

int main()
{
int x,i,n,a[100],s,d,m,gasit=0;
fin>>n;
for(i=1;i<=n;i++) fin>>a[i];
fin>>x;
s=1; d=n;
while(s<=d && !gasit)
{
m=(s+d)/2;
if(a[m]==x) gasit=1;
else if(a[m]<x) s=m+1;
else d=m-1;
}
if(gasit) fout<<m;
else fout<<"Nu se gaseste";
fin.close();
fout.close();
return 0;
}

8. Se citeste un numar real x. Sa se calculeze radical de ordinul 3 din x folosind un algoritm de


tip Divide et impera.

REZOLVARE :

#include<iostream>
using namespace std;
double r3(double x, double s, double d)
{
if(d-s<=0.0001) return d;
else
{ double m=(s+d)/2;
if(m*m*m<x) return r3(x,m,d);
else return r3(x,s,m);
}
}

int main()
{ double x;
cin>>x;
if(x>0) if(x<1) cout<<r3(x,0,1);
else cout<<r3(x,0,x);
else if(x>-1) cout<<r3(x,-1,0);
else cout<<r3(x,x,0);
system("pause");
return 0;
}
BACKTRACKING
1. Se citeste un numar natural n. Generati si afisati toate combinatiile de cate n cifre binare care
nu au doua cifre de 1 alaturate. 
Exemplu: 
n=3 
combinatiile sunt: 
0 0 0 
0 0 1 
0 1 0 
1 0 0 
1 0 1 

REZOLVARE :

#include <fstream>
using namespace std;
ifstream is("date.in");
ofstream os("date.out");

int x[15],n;

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

void back01(int k)
{
for(int i=0;i<=1;i++)
{
x[k]=i;
if(k>1) if(x[k]*x[k-1]!=1)
if(k==n) afis();
else back01(k+1);
else ;
else back01(k+1);
}
}

int main()
{
is>>n;
back01(1);
is.close();
os.close();
return 0;
}
2. Sa se afiseze in ordine alfabetica anagramele unui cuvant format din litere distincte. 
Exemplu: 

date.in date.out
rac  acr
arc 
car 
cra 
rac 
rca

REZOLVARE :

#include <cstring>
#include <fstream>
using namespace std;
ifstream is("date.in");
ofstream os("date.out");
int n;
char v[100],st[50], p[50];
void scrie() //afisez litere conform permutarii
{
int i;
{
for(i=1;i<=n;i++)
os<<v[st[i]-1];
os<<'\n';
}
}

void back(int k) //generez permutarile multimii {1,2,...n}


{
for(int i=1;i<=n;i++)
if(!p[i])
{
st[k]=i;
p[i]=1;
if(k==n) scrie();
else back(k+1);
p[i]=0;
}
}

int main()
{
int i;
is.get(v,1000);
n=strlen(v);
for(int i=0;i<n;i++) //ordonez alfabetic literele din cuvantul citit
for(int j=i+1;j<n;j++)
if(v[i]>v[j])
{ char aux=v[i]; v[i]=v[j]; v[j]=aux; }
back(1);
return 0;
}
3. Se citeste un numar natural n. Afisati permutarile multimii 1,2,3...n in care elementele pare
sunt puncte fixe (se afla pe pozitie egale cu valoarea lor). 
Exemplu: 
n=5 
permutarile care respecta conditia sunt: 
1 2 3 4 5 
1 2 5 4 3 
3 2 1 4 5 
3 2 5 4 1 
5 2 1 4 3 
5 2 3 4 1 
(2 si 4 sunt puncte fixe) 

REZOLVARE :

#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

int n, sol[40], p[40];

void afis()
{
for(int i=1;i<=n;i++)
if(i%2==0) fout<<i<<" ";
else fout<<sol[i]<<" ";
fout<<endl;
}

void back(int k)
{
for(int i=1;i<=n;i=i+2)
if(p[i]==0)
{
sol[k]=i;
p[i]=1;
if(n%2==0 && k==n-1 || n%2==1 && k==n) afis();
else back(k+2);
p[i]=0;
}
}

int main()
{
fin>>n;
back(1);
fin.close();
fout.close();
}
4. Se citeste un numar natural n. Afisati permutarile multimii 1,2,3...n in care pana la jumatate
elementele sunt in ordine descrescatoare, iar de la jumatate pana la final in ordine
crescatoare. 
Exemplu: 
n=5 
permutarile care respecta conditia sunt: 
3 2 1 4 5 
4 2 1 3 5 
4 3 1 2 5 
5 2 1 3 4 
5 3 1 2 4 
5 4 1 2 3 

REZOLVARE :

#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

int n, sol[20], p[20];

void afis()
{
for(int i=1;i<=n;i++)
fout<<sol[i]<<" ";
fout<<endl;
}

int valid(int k)
{
if(k>1)
if(k<=(n+1)/2) { if(sol[k]>sol[k-1]) return 0; }
else if(sol[k]<sol[k-1]) return 0;
return 1;
}

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

int main()
{
fin>>n;
back(1);
fin.close();
fout.close();
}
5. Se citesc doua numere naturale n si k, k fiind mai mic decat numarul de cifre ale numarului n.
Afisati cel mai mare numar care se poate forma eliminand k cifre din numarul n. 
Exemplu: 
n=3452234 
k=4 
numarul cautat este 534

REZOLVARE :

#include <iostream>
using namespace std;

int n, a[10],x[10],maxx,k;

int numar(int a[10],int x[10], int c)


{
int nr=0;
for(int i=1;i<=c;i++)
nr=nr*10+a[x[i]];
return nr;
}

void back(int k, int c)


{
for(int i=n;i>=1;i--)
if(i<x[k-1] || k==1)
{
x[k]=i;
if(k==c)
{
int nr=numar(a,x,c);
if(nr>maxx) maxx=nr;
}
else back(k+1,c);
}
}

int main()
{
cin>>n>>k;
int i=0;
while(n)
{
a[++i]=n%10;
n=n/10;
}
n=i;
back(1,n-k);
cout<<maxx;
return 0;
}

6. Se citesc doua numere naturale n si k. Generati si afisati toate toate numerele naturale
formate din n cifre care contin exact k cifre de 1.

REZOLVARE :
#include <iostream>
using namespace std;
int x[50],n,k;

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

int valid(int pas)


{
int c=0;
for(int i=1;i<=pas;i++)
if(x[i]==1) c++;
if(c>k) return 0;
if(pas==n && c!=k) return 0;
if(x[1]==0) return 0;
return 1;
}

void back(int pas)


{
for(int i=0;i<=9;i++)
{
x[pas]=i;
if(valid(pas)) if(pas==n) afis();
else back(pas+1);
}
}
int main()
{
cin>>n>>k;
back(1);
return 0;
}

7. Se citeste un numar natural n. Afisati toate numerele formate din n cifre in care oricare doua
cifre alaturate au paritate diferita. 
Ex. Pentru n=4 se vor obtine: 
1010 
1012 
... 
2101 
2103 
... 
9898
REZOLVARE :

#include<fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

void afis(int x[], int n)


{
for(int i=1;i<=n;i++) fout<<x[i];
fout<<endl;
}
int bun(int x[], int k)
{
if(x[1]==0) return 0;
if(k>1) if(x[k-1]%2==x[k]%2) return 0;
return 1;
}

void back(int x[], int n, int k)


{
int i;
for(i=0;i<=9;i++)
{
x[k]=i;
if(bun(x,k)) if (k==n) afis(x,k);
else back(x,n,k+1);

int main()
{
int x[100],n;
fin>>n;
back(x,n,1);
fin.close();
fout.close();
return 0;
}

8. Sa se afiseze toate numerele naturale formate doar din cifre impare distincte, sa se calculeze
suma si numarul acestora
REZOLVARE :

#include<iostream>
using namespace std;

int x[100],pus[100],n,p,nr=0, suma=0;

void Write(int p)
{ for(int i=1;i<=p;i++) cout<<x[i];
cout<<endl;
int a=0;
for(int i=1;i<=p;i++) a=a*10+x[i];
suma=suma+a;
nr++;
}
void Aranj(int k, int p)
{ for(int i=1;i<=9;i=i+2)
if(!pus[i])
{ x[k]=i;
pus[i]=1;
if(k==p) Write(p);
else Aranj(k+1,p);
pus[i]=0;
}
}
int main()
{ n=5;
for(p=1;p<=5;p++) Aranj(1,p);
cout<<"suma este"<<suma<<" din "<<nr<< "numere";
return 0;
}
9. Se citeste un numar natural n. Sa se afiseze in fisierul text cuv.out toate cuvintele de n litere
formate doar din litere mici care nu au doua voale alaturate si nici 2 consoane alaturate.

REZOLVARE :

#include<fstream>
#include<string>

int n;
char x[20];
ofstream f("cuv.out");
char v[]="aeiou";

void afis()
{ for(int i=1;i<=n;i++) f<<x[i];
f<<endl;
}

int cond(int k)
{ for(int i=1;i<k;i++) if(x[i]==x[k]) return 0;
if(k>1)
{
if(strchr(v,x[k-1])!=0 && strchr(v,x[k])!=0) return 0;
if(strchr(v,x[k-1])==0 && strchr(v,x[k])==0) return 0;
}
return 1;
}

void back(int k)
{ char i;
for(i='a';i<='z';i++)
{ x[k]=i;
if(cond(k)) if(k==n) afis();
else back(k+1);
}
}

void main()
{ cin>>n;
back(1);
f.close();
}

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