Sunteți pe pagina 1din 18

Metoda Backtracking

Plata unei sume S



Popovici Daniel Gabriel
LICEUL TEORETIC DUNAREA
CLASA A XI A D
PROFESOR INDRUMATOR: BIBICU DORIN


Problema plii unei sume s utiliznd
m tipuri de monede
Se dau suma s si m tipuri de monede
avnd valorile a1, a2, ..., am lei. Se cer
toate modalitile de plat a sumei s
utiliznd aceste monede.
Va trebui s se genereze toi vectorii
de forma X=(x1,...xm), care verific
relaia:
x
1
a
1
+x
2
a
2
+...+x
m
a
m
=S


Din aceast relaie se poate vedea c:
x
1
poate lua valori ntre 0 i n
1
=
x
2
poate lua valori ntre 0 i n
2
=
......................................................
x
k
poate lua valori ntre 0 i n
k
=
.......................................................
x
m
poate lua valori ntre 0 i n
m
=

Trebuie s se determine elementele mulimii:
{x1,,xm}| xk{0,,m} unde k=1,,m i
x
1
a
1
+x
2
a
2
+...+x
m
a
m
=S

Exemplu: S=3; m=2, a[1]=1,
a[2]=2.
Programul va genera soluiile:
(1,1) ce corespunde la
1a1+1a2=11+12=3
(3,0) ce corespunde la
3a1+0a2=31+02=3


0 1 n
m

0 1 n
m-1


0 1 n
2


0 1 n
1

1
m
k
x
k
n
k
Programul
#include<iostream.h>
typedef int sir[100];
sir x,n,a;
int m,i,k,S,as,ev;

void succ(sir x, int k, int &as)
{
if(x[k]<n[k])
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}
void valid(int &ev)
{
ev =1;
}

void afis(sir x,int k)
{
int i,s1;
s1=0;
for(i=1;i<=k;i++)
s1=s1+x[i]*a[i];
if(S==s1)
{
for(i=1;i<=k-1;i++)
cout<<x[i]<<"*"<<a[i]<<"+";
cout<<x[k]<<"*"<<a[k]<<"="<<S<<endl;
}
}

int main(void)
{
cout<<"Dati valoarea sumei:"; cin>>S;
cout<<"Dati numarul monedelor m="; cin>>m;
cout<<"Dati valorile celor "<<m<<" monede: ";
for(i=1;i<=m;i++)
{
cin>>a[i];
n[i]=S/a[i];
}
k=1;
x[k]=-1;

while(k>0)
{
do
{
succ(x,k,as);
if(as) valid(ev);
}
while(as&&!ev);
if(as)
if(k==m) afis(x,k);
else
{
k=k+1;
x[k]=-1;
}
else k=k-1;
}
}

Plata unei sume de bani

ENUNT: Avand la dispozitie n
saculeti cu monede S1, S2, .... Sn,
fiecare saculet Si continand Nri
monede de valoare Vi sa se afiseze
toate modalitatil de a plati o suma
data S folosind numai monezi din
saculeti.

EXEMPLU: Pentru n=3 , Nr=(10,2,5),
V=(1,2,5) si S=5 programul va
genera
5 * 1 leu
3 * 1 leu + 1 * 2 lei
1 * 1 leu + 2 * 2 lei
1 * 5 lei

SOLUTIE:

Solutia x[1]......x[n]. Elementul x[i]
va avea ca valoare numarul de
monede care s-au folosit din
saculetul i
x[k] poate avea ca valoare orice
valoare din intervalul [0,Nrk].
Valid
daca k<n --> suma platita pana la acel
moment sa nu depaseasca S
daca k=n --> suma platita sa fie egala
cu S

PROGRAM C++:
#include <iostream>
using namespace std;

char sp5[]=" ";
int x5[20], n5, nrsol5=0, nr[20], val[20],
sum[20], S;

int Valid5(int k)
{ sum[k]=sum[k-1]+val[k]*x5[k];
if (sum[k]>S) return 0;
if (k==n5 && sum[k]!=S) return 0;
return 1;
}
void Afisare5()
{ int i,j;
cout<<sp5;
for(i=1;i<=n5;i++)
if (x5[i]!=0) cout<<x5[i]<<"*"<<val[i]<<" lei + ";
cout<<endl;
nrsol5++;
}

void Back5()
{ int k=1, cand;
x5[1]=-1;
while (k>0)
{ cand=0;
while (cand==0 && x5[k]<nr[k])
{ x5[k]++;
cand=Valid5(k);
}
if (cand==0) k--;
else if (k==n5) Afisare5();
else {k=k+1; x5[k]=-1;}
}
}
int main()
{ int i;
cout<<endl<<endl<<sp5<<"Plata unei sume de
bani"<<endl;
cout<<endl<<sp5<<" Numarul tipuri monezi: ";
cin>>n5;
cout<<sp5<<" Dati suma de plata: "; cin>>S;
cout<<endl;
for (i=1;i<=n5;i++)
{ cout<<sp5<<" Valoare moneda tip "<<i<<": ";
cin>>val[i];
cout<<sp5<<" Numar monezi tip "<<i<<" : ";
cin>>nr[i];
}
cout<<endl<<"Solutiile sunt: "<<endl;
Back5();
cout<<endl<<sp5<<"Numar solutii: "<<nrsol5;
return 0;
}


Concluzie
Problemele de acest gen nu sunt
foarte grele. Deoarece le-am inteles
mai mult decat alte genuri. Plata unei
sume S este cea mai potrivita pentru
mine pentru a lua o nota buna!

Bibliografie
Caietul de Informatica de clasa
http://lectiiback.blogspot.ro/2010/02/pl
ata-unei-sume-utilizand-n-tipuri-
de.html
https://sites.google.com/site/atestat20
13lmk/probleme-rezolvate/plata-unei-
sume-de-bani

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