Conf.univ.dr.DORUANASTASIUPOPESCU ABSOLVENT CRISTINACALACAN Pitești 2020 2UNIVERSITATEADINPITEȘTI FACULTATEADEȘTIINȚE,EDUCAȚIEFIZICĂȘIINFORMATICĂ… [611419]
1UNIVERSITATEADINPITEȘTI
FACULTATEADEȘTIINȚE,EDUCAȚIEFIZICĂȘIINFORMATICĂ
PROGRAMDESTUDIILICENȚĂ
LUCRAREDELICENȚĂ
COORDONATORȘTIINȚIFIC
Conf.univ.dr.DORUANASTASIUPOPESCU
ABSOLVENT: [anonimizat]
2020
2UNIVERSITATEADINPITEȘTI
FACULTATEADEȘTIINȚE,EDUCAȚIEFIZICĂȘIINFORMATICĂ
PROGRAMDESTUDIILICENȚĂ
FOLOSIREATEHNICILORDEPROGRAMAREPENTRU
REZOLVAREAPROBLEMELORDEMATEMATICĂ
COORDONATORȘTIINȚIFIC
Conf.univ.dr.DORUANASTASIUPOPESCU
ABSOLVENT: [anonimizat]
2020
3Introducere……………………………………………………………………………………………………….4
CAPITOLULI:MetodaBacktraking……………………………………………………………………5
I.1.Generareapermutărilormulțimii…………………………………………………………….9
I.2.Generareaaranjamentelor…………………………………………………………………11
I.3.Generareacombinărilor……………………………………………………………………….12
I.4)PRODUSCARTEZIAN……………………………………………………………………..14
I.5.Submulțimileuneimulțimi…………………………………………………………………..15
I.6)Partițiileunuinumăr……………………………………………………………………………16
I.7)Problemaparantezelor:………………………………………………………………………..17
I.8)Anagrameleunuicuvânt………………………………………………………………………18
I.9.Descompunereaunuinumărînsumadenumereprime……………………………19
I.10)Problemacelorndamepeotablădeșah………………………………………………21
I.11..Problemacomisuluivoiajor(agentuluidevânzări)……………………………….28
I.12)Pătratemagice…………………………………………………………………………………..30
I.13)Problemalabirintului:……………………………………………………………………….32
I.14)Sărituracalului…………………………………………………………………………………35
I.15)Sudoku…………………………………………………………………………………………….37
CapitolulalII-lea:MetodaGreedy…………………………………………………………………….40
II.1)Problemabanilor……………………………………………………………………………….40
II.2:Problema:Fracțiaegipteană……………………………………………………………….41
II.3)ProblemaColorăriihărților…………………………………………………………………43
II.4)Problema:Programareaspectacolelor………………………………………………….45
II.5)ProblemaComisvoiajorul………………………………………………………………….47
II.6)ProblemaRucsacului(fracționară)……………………………………………………….48
II.7)ProblemaHoțiișipolițiștii………………………………………………………………….49
II.8)ProblemaRafturilor……………………………………………………………………………51
II.9)ProblemaSumaariilorunordreptunghiuri…………………………………………….52
II.10)ProblemaRezervărilorîncadrulunuihotel…………………………………………54
II.11)ProblemaOrdinealexicografică…………………………………………………………55
II.12)ProblemaSarciniledelucru………………………………………………………………57
CapitolulalIII-lea:DIVIDEETIMPERA…………………………………………………………58
III.1)Problemă:Sumaelementelordintr-unvector………………………………………..59
III.2)Celmaimaredivizorcomun………………………………………………………………60
III.3).Rădăcinadeordin3………………………………………………………………………….61
III.4)MergeSort……………………………………………………………………………………….61
III.5)QuickSort………………………………………………………………………………………..63
III.6)Căutareabinară………………………………………………………………………………..65
III.7)Sumaelementelorprimedintr-unvector……………………………………………..66
III.8)Sumaprodusdedoitermeniconsecutivi……………………………………………67
III.9)Metodabisectieiuneifunctiipeintervale…………………………………………….68
Bibliografie:……………………………………………………………………………………………………69
4Introducere
Înrezolvareaproblemelordematematică,nuexistădoarunsingur
algoritmcaresăfiesoluțiatuturor.Înfuncțiedecomplexitateaproblemelorde
matematică,poțifolosidiferitetehnicideprogramarepentruaobținesoluțiiledorite.
TemaacesteilucrăriesteFolosireatehnicilordeprogramarepentru
rezolvareaproblemelordematematicășiconținemetodele:Backtracking,Greedyși
DivideetImpera.
PrimulcapitolabordeazămetodaBacktracking.Aceastămetodăajutăla
rezolvareaproblemelorundetrebuiesăscriemtoatesoluțiilesale.Esteometodacare
necesitămulttimpșinumereupoatefiaplicată.Backtrackingulesteometodă
importantăpentrurezolvareasauîndeplinireaunorconstrângeridinproblemeca:
sudoku,puzzleurietc,pentruoptimizareaunorproblemedecombinatorică.
Backtraking-ulesteadeseafolositînlimbajeledeprogramarelogicăcaIcon,Planner
sauProlog.
ÎnaaldoileacapitolesteprezentatămetodaGreedy.Aceastămetodăiaîn
considerareconstrucțiauneisoluțiioptime,fărăsăconstruiascătoatesoluțiileposibile.
Aceastămetodapoatefiaplicatăcusuccesînproblemeledematematicăatuncicând
avemofuncțieobiectiv(deminimizaresaumaximizare).AlgorimulGreedyface
alegerilafiecarepasșiîntotdeaunaseasigurăcăfuncțiaobiectivesteoptimizată.Un
dezavantajalacesteimetodeestecătrebuiesămunceștimaimultpentruaînțelegeși
rezolvaproblemeledinpunctdevederealconstrângerilor,alcondițiilor.
Ultimulcapitolprezintădiferiteproblemecareserezolvăcuajutorul
metodeiDivideetImpera.Numărulacestorproblemeesterelativmic,deoarecenu
oriceproblemădematematicăpoatefidescompusăîndiferitesubproblemedeacelași
tip.
5CAPITOLULI:MetodaBacktraking
Decelemaimulteoriînpractică,avemderezolvatproblemecareauun
numărmaredesoluțiiposibile.Uneoriînsă,nuneintereseazătoatesoluțiile,cidoar
aceleacareîndeplinescanumitecondițiispecificeproblemei.Pentruacesttipde
problemeesteindicatsăfolosimmetodabackstracking.
Backtrackings-arputeatraduce"urmărireînapoi"ceeacesugereazăfaptulcă
oricevectorsoluțieesteconstruitprogresiv,începândcuprimacomponentăși
mergândcătreultima,cueventualereveniri(urmăriri)asupravaloriloratribuite
anterior(cuunulsaumaimulțipașiînapoi).
Termenul„backtrack”afostinventatdematematicianulamericanD.H.Lehmer
înanii1950.
Backtrackingulesteutillarezolvareaunorproblemedesatisfacerea
constrângerilor,cumarficuvinteleîncrucișate,jocuridesudokușialteprobleme
similare.
MetodaBacktrackingsefoloseșteînrezolvareaproblemelorcareîndeplinesc
simultanurmătoarelecondiții:
1.Trebuiegeneratetoatesoluțiileproblemei
2.Soluțiapoatefipusăsubformaunuivectoracăruielementeaparținunor
mulțimifiniteșiseaflăîntr-oordinestabilită
3.Nusedispunedenicioaltărezolvaremairapidă
MetodaBacktrackingesteunadestuldecostisitoare,însensulcăeaconsumă
multtimpșimultămemorie,darsuntproblemepracticepentrucarenuavemalte
metodemaibunederezolvare.Uneledintreelevorfirezolvateînacestcapitol.
Chiardacăeometodăcostisitoare,pentruanumiteproblemeeanupoatefi
evitată,neexistândaltemetodecuoeficiențămaibună.Easedovedeșteutilăîn
problemeșijocuridelogică(cumarfijoculdeșah,joculsudoku,foartemultejocuri
detippuzzle,rebusșialtele),înuneleaplicațiidindomeniulmatematiciicumarfi:
generareapermutărilor,aaranjamentelor,combinări,partițiialeuneimulțimi,etc.
Descriereametodei:BACKTRAKING
Backtrackingesteotehnicăcaresefoloseștepentruadecidecaresoluțiinu
trebuiescfigenerate.
Backtrackingesteunalgoritmpentruarezolvaproblemerecursivîncercândsă
construiascăsoluțiaprinincrementare,câteoparteperând,înlocuindacelesoluții
carenusatisfaccondițiileproblemeilaunanumitmomentdat.
Acestecondițiispecificeproblemeisenumesccondițiidevalidaresau
condițiiinterne.
Soluțiilesuntconstruiteîntr-omanierăincrementalăpringăsireasuccesivăa
valorilorpotrivitepentrucomponente(lafiecareetapăsecompleteazăocomponentă;
6osoluțieîncaredoaropartedintrecomponentesuntcompletate,senumeștesoluție
parțială.
Fiecaresoluțieparțialăesteevaluatăcuscopuldeastabilidacăestevalidă.O
soluțievalidăpoateconducelaosoluțiefinală,pecândunainvalidăîncalcă
restricțiileparțiale,ceeaceînsemnăcănuvaconduceniciodatălaosoluțiecaresă
satisfacătoaterestricțiileproblemei.
Dacăniciocomponenentănuconducelaosoluțieparțialăvalidă,atuncise
revinelaocomponentăanterioarășiseîncearcăaltăvaloarepentruaceasta.
Soluțiileproblemeisevorgenerarândperândîntr-ostivăimplementatăsubforma
unuivectorpecareîlvomnotast.
Reamintim:
A)StivafuncționeazădupăprincipiulLIFO(lastin,firstout)
B)Pentruasimulacaracteruldestivă,vomobservavectorulstcașicumelementele
salesuntașezatepeverticală,unulpestealtul.
Metodautilizeazăstructuradetipstivășipoatefiprogramatăatâtiterativcâtși
recursiv.
Stivaesteaceaformădeorganizareadatelor(structurădedate)cuproprietatea
căoperațiiledeintroducereșiscoatereadatelorsefacînvârfulei.
C)Îngeneral,număruldeelementecareintrăîncomponențasoluțiilor,poatesădifere
delaosoluțielaalta.Pentruînceputvomstudiacazulîncaretoatesoluțiileauacelași
numărdeelemente.
Stivastvaconțineunnumărdenelemente.Astfeloconfigurațieavectorului
stivăstformatădinelementele(1st,2st,3st,…,nst)sevanumisoluțiefinală.
Fiecaresoluțieistvaluavaloridintr-oanumitămulțimeiS,cui=1,2,…,n.
Particularizămșiconsiderămcătoatecomponenteleistiauvaloriînaceeași
mulțimeS.
AnsamblulmulțimiloriS,adicăprodusulcarteziannSSS …2 1 se
numeștespațiulsoluțilorposibile.
DimensiuneaspațiuluisoluțiilorposibileestenScardScardScard … 2 1 .
Fiecaresoluțievaficonstruităînstivast,pascupas,completândstivanivelcu
nivel.
Astfelpentruaobțineosoluțiefinalăcunnivele,deformast=
(1st,2st,3st,…,nst),vomanalizanișteconfigurațiiintermediarealestivei
numitesoluțiiparțiale.
Cualtecuvinte,osoluțieparțială(1st,2st,3st,…,kst),undekvalua
succesivtoatevaloriledela1lan.Larândulsăufiecaresoluție
(1st,2st,3st,…,kst),seobțineprincompletarecuîncăunnivelasoluțieparțiale
anterioarest=(1st,2st,3st,…,1kst ).
7Etapeînproiectareaalgoritmului:
1)Sealegemoduldereprezentareasoluților.
2)SeidentificăspațiulsoluțiilorposibileșisestabilescmulțimilenSSS …,, ,2 1 și
ordineaîncareacesteavorfiparcurse.
3)Sestabilesccondițiilepecaretrebuiesăleîndeplineascăsoluțiileparțialepentrua
fivalide.
4)Sestabileștecondițiadebazăcaredecidedacăosoluțieparțialăestesoluțiefinală.
5)Lafiecarepasppornimdelaosoluțieparțialăst=(1st,2st,3st,…,1kst ),
determinatăpânăînacelmomentșiîncercămsăextindemaceastăsoluțieadăugândun
nouelementlasfârșitulvectorului.
6)CăutămînmulțimeakS,unnouelement.
7)Dacăexistăunelementneselectatîncă,verificămdacăacestelementîndeplinește
condițiileimpusedeproblemă,numitecondițiidecontinuare.
8)Dacăsuntrespectatecondițiiledecontinuare,adăugămelementulsoluțieiparțiale.
9)Verificămdacăamobținutosoluțiecompletă.
10)Dacăamobținutosoluțiecompletăoafișămșisereiaalgoritmuldelapasul5
11)Dacănuamobținutosoluție,k<––k+1sisereiaalgoritmuldelapasul5.
12)Dacănusuntrespectatecondițiiledecontinuaresereiaalgoritmuldelapasul6.
13)DacănumaiexistăniciunelementneverificatînmulțimeakSînseamnăcănu
maiavemnicioposibilitatedinacestmoment,săconstruimsoluțiafinalăașacă
trebuiesămodificămalegerilefăcuteînprealabil,astfelk<–-k-1șisereiaproblema
delapasul5.
Îngeneral,metodabacktrackingesteineficientăavândcomplexitatea
exponențială.
DacămulțimilenSSS ,…, ,2 1 auacelașinumărpdeelemente,timpulnecesareste
npO ,deciexponențial.Dacănuauacelașinumărdeelemente,notămcu
s=min npppp …,,3 2 1 șicuu=max npppp …,,3 2 1 .Atuncitimpuldeexecuțieesteun
numărcuprinsîntre )(nsO și )(nuO ,decitotexponențial.
Cutoateacestelucrurimenționate,existătreitipurideproblemecareserezolvă
cuajutorulmetodeibacktracking:
1.Problemededecizie-secautăosoluțiefezabilă
2.Problemedeoptimizare-secautăceamaibunăsoluție
3.Problemedeenumerare-secautătoatesoluțiileposibile.
Deciavânduntimpdeexecuțieexponențial,utilizareaacesteimetode,estejustificată
doaratuncicândnucunoaștemoaltămetodăderezolvarecueficiențămaimare.
Revenireaîncazdeinsuccessaupentrugenerareatuturorsoluțiilor
problemeiacondusladenumireadebacktracking,întraducereaproximativăar
firevenireadinurmă.
Utilizareaalgoritmuluirecursivametodeibacktrackingestemultmaiușoarășimai
naturală.Segmentuldestivăpusladispozițieprinfuncțieestegestionatautomatde
sistem.Întotdeaunasevarevenilapasulanteriorprinînchidereaniveluluidestivă.
8BacktrakingAlgoritmrecursiv
} } }1) (k Back elsepar(k) ti1) solutie(k) {if1) (valid(k) ; {) i n; i 1; (i for i; int {k) Back(int
ifikstvoid
Subprogramulvalid
1.verificădacăunelementeîndeplineștecondițiadecontinuare
2.Dacăesteverificatăcondiția,aceastăfuncțiereturnează1,și0încazcontrar.
intvalid(intk)
{for(inti=1;i<k;i++)
if(conditie)
return1;
return0;
}
Subprogramulsolutie
1.Verificădacăs-auobținuttoateelementelesoluției.
2.Dacăs-agăsitsoluțiavareturna1,altfel0.
intsolutie(intk)
{if(k==n)
return1:
return0;}
Subprogramultipar
1.Afișeazăelementeledinstivă.
2.Afișareaelementelordinstivăcoincidecuafișareasoluției.
voidtipar()
{for(inti=1;i<=n;i++)
cout<<st[i]<<”“;}
9Permutări.Aranjamente.Combinari
Algoritmînpseudocod
(soluțiicuacelașinumărdecomponente=n)
k=1;
st[k]=0;//inițializarestivă
while(k>0)
if(k==n+1)//configurațiaedetipsoluție
tipar();
k–;
else
if(existăvalorineconsumateînSk)
{seatribuieovaloarepentruxkSk!
if(valid(k))//valoareaaleasăsatisfacecondițiiledecontinuare
{k++;
st[k]=0;
}
}
else
{st[k]=0;
k–;
}
I.1.Generareapermutărilormulțimii
Enunț:Seciteștedelatastaturăunșirdennumerenaturaledistinctedouă
câtedouă.Realizațiunprogramcaresăafișezetoatepermutărileșiruluidat.
Dacăn=3,mulțimile 3,2,13 2 1 SSS
Soluțiilearfi:
{123,132,213,231,312,321}
Dacăs-arrezolvaclasicaceastăproblemă,arînsemnacăartrebuisăgenerăm
toateelementeleprodusuluicartezian: 3,2,13,2,13,2,13 2 1 SSS ,adicăo
mulțimeformatădinelementele: 3,3,3,2,3,3,…2,1,1,1,1,1 .Deoarecefiecare
soluțiefinalăartrebuisăaibătoateelemenetelediferite,dinlistamenționată,doar
șaseîndeplinesccondițiaimpusă.
Seobservă,căelementelemulțimilorsuntînordinestrictcrescătoareși
consecutive.Așadarmoduldealegeredinmulțimenuestealeatoriu,cisefaceîn
funcțiedeordineaelementelor.
st=(st1,st2,st3)S={1,2,3}x{1,2,3}x{1,2,3}
Numărulsoluțiilor:3!=6
Condițiiinterne:st[i]st[k] ki
10Generămcuajutorulstivei,soluțiileprimmetodabacktracking.
1 2 3
1 2 2 2 2
1 1 1 1 1 1
1 2 3
3 3 3 3 1
1 1 1 1 2 2
1 2 3 1
1 1 1 2 3 3
2 2 2 2 2 2
#include<iostream>
usingnamespacestd;
charsp1[]=""; ";
intst[10],n;
voidtipar()
{inti;
cout<<sp1;
for(i=1;i<=n;i++)
cout<<st[i]<<"";
cout<<endl;
;
}
intvalid(intk)
{inti;
for(i=1;i<=k-1;i++)
if(st[k]==st[i])return0;
return1;
}
voidBack(intk)
{inti;
for(i=1;i<=n;i++)
{st[k]=i;
if(valid(k))
if(k==n)tipar();
elseBack(k+1);
}
}
intmain()
{cout<<endl<<sp1<<"Dativaloarealuin:";cin>>n;
cout<<"Permutarileprimelornnumerenaturale"<<endl;
11cout<<endl;
Back(1);
return0;
}
I.2.Generareaaranjamentelor)! (!
pnnAp
n
Secitescnșip.Săsegenerezetoatearanjamenteledenluatecâtep.
Dinanalizaproblemeirezultăurmătoarele:
-stivaareînălțimeap;
-fiecareniveliavaloriîntre1șin;
-elementeleplasatepediverseniveluritrebuiesăfiedistincte.
Algoritmulesteasemănătorcuceldelapermutări,cudeosebireacăaicistiva
areînălțimeap.
Exemplu:
{1,2,3}p=2 6!1!32
3A
{1,2},{1,3},{2,1}{2,3},{3,1},{3,2}
Condițiiinterne:st[i]!=st[k]ki
#include<iostream>
#include<conio.h>
usingnamespacestd;
intst[20],n,k;
voidtipar(intp)
{
intj;
for(j=1;j<=p;j++)
cout<<st[j]<<"";
cout<<endl;
}
intvalid(intp)
{
inti,ok;
ok=1;
for(i=1;i<p;i++)
if(st[p]==st[i])
ok=0;
12returnok;
}
intsolutie(intp)
{
return(p==k);
}
voidback(intp)
{
inti;
for(i=1;i<=n;i++)
{
st[p]=i;
if(valid(p))
if(solutie(p))
tipar(p);
else
back(p+1);
}
}
intmain()
{inti;
cout<<"n=";cin>>n;
cout<<"k=";cin>>k;
for(i=1;i<=n;i++)
st[i]=0;
back(1);
system("pause");
}
I.3.Generareacombinărilor!)! (!
kknnCk
n
{1,2,3}k=2 3!2!1!32
3C
Fiinddatedouănumerenșik,seceresăsegenerezetoatecombinăriledenelemente
luatecâtek.
Rezolvare:
Ceeacenepropunemestesăgenerămcombinăriledenelementeluatecâtek.
Fiecaresoluțievafioconfigurațieastivei(st[1],st[2],…,st[k])alcătuitădink
elementedistinctealemulțimii1,2,3,…,n
Notândcupvârfulstivei,osoluțieparțială(st[1],st[2],…,st[p])devinefinală,când
stivaarekelemente,adicădacăp=k.
Condițiiinterne:st[k]>st[k-1] 1k
13#include<iostream>
usingnamespacestd;
intn,p,st[25];
intvalid(intk);
intsolutie(intk);
voidtipar(intk);
voidback(intk);
charsp1[]="";
intmain()
{cout<<endl<<sp1<<"Dativaloarealuin:";cin>>n;
cout<<endl<<sp1<<"Dativaloarealuip:";cin>>p;
cout<<"Combinariledenluatecatep"<<endl;
cout<<endl;
back(1);
return0;
}
voidback(intk)
{inti;
for(i=st[k-1]+1;i<=n;i++)
{st[k]=i;
if(valid(k))
{if(solutie(k))
tipar(k);
else
back(k+1);
}
}
}
intvalid(intk)
{inti;
for(inti=1;i<k-1;i++)
if(st[i]==st[k])
return0;
return1;
}
intsolutie(intk)
{if(k==p)
return1;
return0;
}
voidtipar(intk)
{inti;
for(inti=1;i<=k;i++)
cout<<st[i]<<"";
cout<<endl;
}
14I.4)PRODUSCARTEZIAN
Fiinddatenmulțimi,nMMM ,…, ,2 1 săseafișezeelementeleprodusuluicartezian
nMMM …2 1 undei in M ,…,3,2,1 .
ProdusulcartezianalmultimilorM1,M2,M3,…,Mn
Dativaloarealuin:4
CardinalulMultimii1:2
CardinalulMultimii2:3
CardinalulMultimii3:1
CardinalulMultimii4:1
1111
1211
1311
2111
2211
2311
#include<iostream>
usingnamespacestd;
charsp[]=" ";
intst[20],n,v[20];
voidtipar()
{inti,j;
cout<<sp;
for(i=1;i<=n;i++)cout<<st[i]<<"";
cout<<endl;
;
}
voidBack(intk)
{inti;
for(i=1;i<=v[k];i++)
{st[k]=i;
if(k==n)tipar();
elseBack(k+1);
}
}
intmain()
{inti;
cout<<sp<<"ProdusulcartezianalmultimilorM1,M2,M3,…,Mn"<<endl;
cout<<endl<<sp<<"Dativaloarealuin:";cin>>n;
for(i=1;i<=n;i++)
{cout<<"CardinalulMultimii"<<i<<":";cin>>v[i];}
Back(1);
return0;
}
15I.5.Submulțimileuneimulțimi
SăsegenerezetoatesubmulțimilemulțimiiA={1,2,3…,n}.
#include<iostream>
usingnamespacestd;
intn,p,st[25];
intvalid(intk);
intsolutie(intk);
voidtipar(intk);
voidback(intk);
intmain()
{inti;
cout<<"n=";
cin>>n;
cout<<"multimeavida"<<endl;
for(p=1;p<=n-1;p++)
back(1);
cout<<"{";
for(i=1;i<n;i++)
cout<<i<<",";
cout<<n<<"}";
}
voidback(intk)
{inti;
for(i=st[k-1]+1;i<=n;i++)
{st[k]=i;
if(solutie(k))
tipar(k);
else
back(k+1);
}
}
intsolutie(intk)
{if(k==p)
return1;
return0;
}
voidtipar(intk)
{inti;
for(inti=1;i<=k;i++)
cout<<st[i]<<"";
cout<<endl;
}
n=4
16multimeavida
1
2
3
4
12
13
14
23
24
34
123
124
134
234
{1,2,3,4}
I.6)Partițiileunuinumăr
Scriețiunprogramcaresăafișezetoatepartițiileunuinumărnaturaln.
Senumeștepartitieaunuinumărnaturalnenulnomulțimedenumerenaturalenenule
{k1,k2,..,km}știindcăconditiak1+k2+…+km=n.
Pentrun=6avem:
Solutianr.1:111111
Solutianr.2:11112
Solutianr.3:1113
Solutianr.4:1122
Solutianr.5:114
Solutianr.6:123
Solutianr.7:15
Solutianr.8:222
Solutianr.9:24
Solutianr.10:33
Solutianr.11:6
11solutii
#include<iostream>
usingnamespacestd;
intn,ns,sol[20];
voidafis(intl)
{inti;
ns++;
cout<<"Solutianr."<<ns<<":";
for(i=1;i<=l;i++)cout<<sol[i]<<"";
cout<<endl;
}
17voidback(inti,intsp)
{intj;
if(sp==n)afis(i-1);
elsefor(j=1;j<=n-sp;j++)
if(j>=sol[i-1])
{
sol[i]=j;
back(i+1,sp+j);
}
}
intmain()
{
cin>>n;
ns=0;
back(1,0);
cout<<ns<<"solutii";
}
I.7)Problemaparantezelor:
Dându-seunnumărparn,afișațitoatevarianteledenparantezecareseînchidcorect.
Exemplu:
4
(())
()()
Rezolvare:
#include<iostream>
usingnamespacestd;
intst[10],n;
voidscriesol()
{intj;
cout<<endl;
for(j=1;j<=n;j++)
if(st[j]==1)cout<<")";
elsecout<<"(";
}
intcond(intk)
{inti,pi=0,pd=0;
for(i=1;i<=k;i++)
if(st[i]==0)pd++;
elsepi++;
returnpd<=n/2&&pi<=pd;
}
18I.8)Anagrameleunuicuvânt
#include<bits/stdc++.h>
usingnamespacestd;
voidanagrame(strings,intl,intr)
{
if(l==r)
cout<<s<<endl;
else
{
for(inti=l;i<=r;i++)
{
swap(s[l],s[i]);
anagrame(s,l+1,r);
swap(s[l],s[i]);
}
}
}voidback(intk)
{
inti;
for(i=0;i<=1;i++)
{
st[k]=i;
if(cond(k))
if(k==n)scriesol();
elseback(k+1);
}
}
intmain()
{
cin>>n;
back(1);
}
19intmain()
{
stringstr="aer";
intn=str.size();
anagrame(str,0,n-1);
return0;
}
Date.in
Aer
Date.out
aer
are
ear
era
rae
rea
I.9.Descompunereaunuinumărînsumadenumereprime.
ScriețitoatedescompunerilenumăruluiNcasumădenumereprime.
N=7
223
232
25
322
52
7
#include<iostream>
#include<math.h>
usingnamespacestd;
intN,st[10],k;
intdescompunereSuma(intk)
{
intS=0;
for(inti=1;i<=k;i++)
S+=st[i];
returnS;
}
intverificaPrim(intm)
{
if(m<=1)return0;
20for(inti=2;i<=sqrt(m);i++)
if(m%i==0)
return0;
return1;
}
intSolutie(intk)
{
return(descompunereSuma(k)==N);
}
voidTipar(intk)
{
cout<<endl;
for(intj=1;j<=k;j++)
cout<<st[j]<<"";
}
intValid(intk)
{
return((verificaPrim(st[k]))&&(descompunereSuma(k)<=N));
}
voidBack()
{
for(intk=1;k<=N;k++)
st[k]=1;
k=1;
while(k>0)
{
while(st[k]<N)
{
st[k]++;
if(Valid(k))
if(Solutie(k))
Tipar(k);
else
k++;
}
st[k–]=1;
}
}
intmain(void)
{
cout<<"N=";cin>>N;
Back();
}
21Backtrackinggeneralizatsauînplan
Încapitolulanterior,amstudiatmetodabacktracking,șiamobservatcăstiva
stcarememorasoluțiilefinaleeraunvector,adicăuntablouunidimensional.Astfel,
fiecareelementalstiveikst aveaosingurăvaloarelaunmomentdat.
Sepoateîntâmplacaîntr-oproblemăfiecareelementalstiveikst săaibă
maimultecaracteristici?
Răspunsulesteafirmativșicaexemplu,peotablădeșahvremsăobținemtoate
traseelepecarele-arurmauncal,astfelîncâtporninddincolțuldinstângasualtablei,
acestavreasăajungăîncolțuldindreaptajos.Dacăvremsămemorămpestivă,
căsuțeleîncarepoatesăricalul,vomținecontcăfiecarecăsutăaredouăcaracteristici:
liniașicoloana.
Înaceastăsituație,stivastnumaipoatefiuntablouunidimensional,deoarece
fiecareelementkst trebuiesăaibămaimultecaracteristici.
Deaceea,trebuiesădefinimstivacauntabloubidimensional(matrice)sau
tridimensional.
Pentrubacktracking-ulgeneralizatestemaidificildeproiectatunalgoritm
standard,deoarececaracteristicilepecaretrebuiesăleaibăvectorulsoluțiediferăde
laoproblemălaalta.
I.10)Problemacelorndamepeotablădeșah
OproblemăclasicădebacktrackingoreprezintăproblemacelorN-Dame,
propusăpentruprimadatădeșahistulgermanMaxBezzelîn1848,utilizându-sede
psudonimul”Schachfreund”,pentruotablădeșahde8x8,iarîn1869,
Francois-JosephEustacheLionnetpropuneformageneralădenxn.
Pentruaceiacarenusuntfamiliarizațicuregulileșahului,douăreginenu
sepotaflaînaceeașilinie,coloanădiagonalăpentruanuseataca.
Înscrisoareadin1850cătreprietenulsăuHeinrichScumacher,eminentul
matematicianCarlFriedrichGaussasusținutcăademonstratîncâtevaoreșifoarte
ușor,răspunsulluiFranzNauckpentruproblemăcareîncazul8x8,are92soluții.
ScrisoarealuiGaussdescrieurmătoareaformărecursivăastrategieide
rezolvareaproblemeiN-Dame,aceeașipecareadescris-oîn1882,matematicianul
francezEdouardLucasșipecarei-aatribuit-oluiEmmanuelLaquiere.
Plasămdamelepetablă,câteunaperând,începândcuprimulrânddesus.
Pentruaplasaak-damă,vomîncercatoatecelenpătrateînliniakdelastângala
dreaptafolosindu-nedebuclă.Dacăunpătratesteatacatdeoaltădamă,vomignora
acelpătrat,altfelputemplasadamaînelșirecursiv,vomputeaplasafiecaredamăpe
rândpânălaultimalinie.
Figura1,prezintăalgoritmulmenționat,șicareînmodrecursivenumeră
toatesoluțiileproblemeiN-Dame,porninddelaosoluțieparțială.
ConformluimetodeiGauss,noiputemreprezentapozițiiledamelor
utilizândvectorulnQ ,…,2,1 ,undeiQ indicăpătratulicareconțineodamă.Când
PlaseazăDamaesteapelat,parametruldeintrarekesteindexulprimieiliniigoale,iar
prefixul1 ,…,2,1kQ conținepozițiileprimelork-1dameplasatedeja.
22Înparticularpentruacalculatoatesoluțiileproblemeifărărestricții,putem
apelaPlaseazăDama()1,…1(nQ .Ieșireadinbuclaforconsiderătoateposibilitățile
pentruplaseareauneidamepeliniak.Intrareaînbuclafor,verificădacăplasarea
dameiîntr-unpătratpeliniak,nucontrazicepozițiileprimelork-1damedeja
plasat ) () ( ikjiQsauikjiQsaujiQ e.
AlgoritmulGAUSSșiLaquierepentruproblemacelorN-Dame
PlaseazăDama),…1(knQ
Ifk=n+1
printnQ ,…,2,1
Altfel
forj←1ton
legal←TRUE
Fori←1tok-1
If
legal←FALSE
Iflegal
iQ←j
PlaseazăDama )1,…1( knQ
ExecuțiaPlaseazăDamapoatefiilustratăîntr-unarborede
recurență.Fiecăruinoddinacestarboreîicorespundeosupbroblemărecursivă,șicare
reprezintăosoluțieparțialălegală,înparticularfiecarerădăcinăîicorespundeotablă
goală,adicăk=0.Vârfuriledinarborelederecurențăcorespundapelurilorrecursive.
Frunzelecorespundsoluțilorparțialecarenupotmergemaideparte,fiedincauzăcă
existădejacâteoreginăînfiecarepătrat,fiecaindiferentdepozițiadameipe
următoarealinie,nuputemîndeplinicondițiadeanuatacaoaltădamă.Căutarea
backtrackingpentrusoluțiilecompleteesteechivalentăcucăutareaDEPTH_FIRSTa
acestuiarbore.
Fiinddatăotablădeșah,dedimensiunen,xn,secertoatesoluțiiledearanjarea
ndame,astfelîncâtsănuseafledouădamepeaceeașilinie,coloanăsaudiagonală
(damesănuseatacereciproc).
23Exemplu:Săpreuspunemcăavemotablăde4x4și4regine.Atunciosoluție
finalăarfi:
Seobservăcăodamătrebuiesăfieplasatăsingurăpelinie.Așezămprimadamăpe
linia1,coloana1.
Adouadamăpoatefiașezatădoarîncoloana3.
Deci,atreiadamănupoatefiplasatăînlinia3.
Înacestcaznuavemsoluții,deoarececeade-a4damănumaipoatefiașezatăpe
tablăconformcerințelorproblemei.
Așacăvomîncercaatunciplasareaceleide-adouadameîncoloana4.Atreiadamă
nupoatefiplasatădecâtîncoloana2.
24
Încercândsăavansămcudamaapatra,observămcănuesteposibilsăo
plasămniciîncoloana3,niciîncoloana4.Dinnou,nuvomaveasoluție.
Avansămcuprimadamăîncoloana2.
Adouadamănupoatefiașezatădecâtîncoloana4.
Damaatreiaseașeazăînprimacoloană.
Acumesteposibilsăplasămapatradamăîncoloana3siastfelamobținuto
soluțieaproblemei.
Algoritmulcontinuăînacestmodpânăcândtrebuiescoasădepetablăprima
damă.
Pentrureprezentareauneisoluțiiputemfolosiunvectorcuncomponente
(avândînvederecăpefiecareliniesegăseșteosingurădamă).
ExemplupentrusoluțiagăsităavemvectorulSTcepoatefiasimilatuneistive.
Douădamesegăsescpeaceeașidiagonalădacăsinumaidacăesteîndeplinită
condiția:|st(i)-st(j)|=|i-j|(diferența,înmodul,întreliniisicoloaneesteaceeași)
ST(4)
ST(3)ÎngeneralST(i)=ksemnificăfaptulcăpeliniaidamaocupăpozițiak.
ST(2)
ST(1)3
1
4
2
25Exemplu:întabla4x4avemsituația:
st(1)=1i=1
st(3)=3j=3
|st(1)-st(3)|=|1–3|=2
|i–j|=|1–3|=2
sausituația
st(1)=3 i=1
st(3)=1 j=3
|st(i)-st(j)|=|3–1|=2
|i–j|=|1–3|=2
Întrucâtdouădamenusepotgăsiînaceeașicoloană,rezultăcăosoluțieeste
subformădepermutare.Oprimăideeneconducelagenerareatuturorpermutărilorsi
laextragereasoluțiilorpentruproblemacadouădamesănufieplasateînaceeași
diagonală.Aprocedaastfel,înseamnăcălucrămconformstrategieibacktracking.
Aceastapresupunecaimediatceamgăsitdouădamecareseatacă,săreluăm
căutarea.
latăalgoritmul,conformstrategieigeneratedebacktracking:
-Înprimapozițieastiveiseîncarcăvaloarea1,cusemnificațiacăînliniaunu
seașeazăprimadamăîncoloană.
-Linia2seîncearcăașezareadameiîncoloana1,acestlucrunefiindposibil
întrucâtavemdouadamepeaceeașicoloană.
-Înlinia2seîncearcăașezareadameiîncoloana2,însăacestlucrunueste
posibil,pentrucădamelesegăsescpeaceiașidiagonală(|st(1)-st(2)|=|1-2|);
-Așezareadamei2încoloana3esteposibilă.
-Nusepoateplasadama3încoloana1,întrucâtînliniile1-3dameleocupa
acelașicoloană.
-Șiaceastăîncercareeșueazăîntrucâtdameledepe2și3suntpeaceeași
diagonală.
-Dameledepe2-3segăsescpeaceeașicoloană.
-Dameledepe2-3segăsescpeaceeașidiagonală.
-Amcoborâtînstivămutânddamadepelinia2șicoloana3încoloana4.
Algoritmulseîncheieatuncicândstivaestevidă.
Conditiiinterne:
njijijstistjinjijijstistnist
,1,, ,][ ][,1,, ],[ ][},…,2,1{][
Damelenupotfiplasatepeaceeasicoloana
Damelenupotfiplasatepeaceeasi
diagonala
26
#include<iostream>
#include<math.h>
usingnamespacestd;
intst[10],n,i,k,nrsol=0,j;
voidinit()
{for(i=1;i<=n;i++)
st[i]=0;
}
voidtipar()
{for(i=1;i<=n;i++)
{for(j=1;j<=n;j++)
if(st[i]==j)
cout<<"R";
else
cout<<"*";
cout<<endl;
}
}
intvalid(intk)
{for(i=1;i<k;i++)
if(st[i]==st[k]||abs(i-k)==abs(st[i]-st[k]))
return0;
return1;
}
27voidback()
{
k=1;
while(k>0)
if(k==n+1)
{nrsol++;
cout<<"Solutiacunr."<<nrsol<<"este:"<<endl;
tipar();
k–;
}
else
if(st[k]<n)
{st[k]++;
if(valid(k))
k++;
}
else
{st[k]=0;
k–;
}
}
intmain()
{cout<<"n=";cin>>n;
init();
back();
cout<<endl;
cout<<"Nr.sol="<<nrsol<<endl;
}
n=4
Solutiacunr.1este:
*R**
***R
R***
**R*
Solutiacunr.2este:
**R*
R***
***R
*R**
28I.11..Problemacomisuluivoiajor(agentuluidevânzări)
Seconsiderănorașe1,2,3,…,n.Unagentdevânzăritrebuiesăîșiprezinteprodusele
întoatecelenorașe,plecânddintr-unorașdestart,trecândprinfiecareorașdoaro
singurădatășirevenindînorașulîncareaplecat.Știindcăîntreuneledintreorașe
existădrumuridirecte,iarîntrealtelenu,săseafișezetoatetraseelepecarelepoate
urmaagentuldevânzări.
Drumuriledirectedintreorașe,suntmemorateîntr-omatricecunliniișimcoloane,în
carefiecareelementa[i,j]=1dacăexistădrumulîntreceledouăorașe,și0încaz
contrar.
n=5
01001
10110
01011
01100
10100
Plecânddinorașul1,traseeleposibilesunt:(1,2,4,3,5,1)și(1,5,3,4,2,1).
Descriereaalgoritmului:
Notăm-orașelecunumeredela1lan.
-st-vectorulstivă
-sorașuldeplecare
Fiecaresoluțiefinalăvareprezentatraseulcomis-voiajoruluișivaconținetoate
orașele,osingurădată.Decivomavea,defapt,osoluțieformatădinpermutarea
mulțimiin,…,3,2,1 .Opartedinpermutărivorfielimnateautomat,datorită
condițiilordevalidare.
Înfuncțiainit():
-vomcitipen
-vominițializastiva
-vomcompletamatriceaa
-vompunecondițiacatoateelementeledepediagonalaprincipalăsăfie0,adică
000iia
-citimporțiuneadeasupradiagonaleiprincipaleșivomfaceatribuirea
00 00 ijajia ,matriceaafiindunasimetrică,adicădacăexistădrumîntrei0
șij0,vaexistadrumșiîntrej0,i0.
Penivelul0alstiveivomindicaorașuldeplecares.
Verificămvaliditateauneisoluțiiparțialest[1],st[2],…,st[p]șipentruaceasta
vompresupuneîncădelaînceputcăestevalidă,inițializândcu1,ovariabilăbooleană
ok,apoivomcăutacazulcontrar,carearputeafifurnizatdeurmătoarelecondiții:
291.dacăvreunorașsemaigăseștepeunnivelanterior.
2.dacăîntreorașulst[p]șist[p-1]nuexistădrum,înseamnăcădeplasareacomisului
voiajornuareloc.
Osoluțiest[1],st[2],…,st[p]estesoluțiefinalădacăconținenorașeșiîntre
1snsta ,adicăîntreorașulfinalșiceldestartsăexistedrum.
Algoritm:
#include<iostream>
#include<conio.h>
#include<stdio.h>
usingnamespacestd;
inta[25][25];
intst[25],n,s;
voidafis_matrice()
{
inti1,j1;
cout<<"\nMatriceadrumuriloreste:\n";
for(i1=1;i1<=n;i1++)
{
for(j1=1;j1<=n;j1++)
cout<<a[i1][j1]<<"";
cout<<"\n";
}
}
intinit()
{inti0,j0;
cout<<"\nnumaruloraselor=";cin>>n;
cout<<"\norasuldeplecare=";cin>>s;
for(i0=0;i0<25;i0++)
st[i0]=0;
for(i0=1;i0<=n;i0++)
a[i0][i0]=0;
cout<<"\nDatimatriceadrumurilor:\n";
for(i0=1;i0<=n;i0++)
for(j0=1;j0<=n;j0++)
if(i0<j0)
{
cout<<"a["<<i0<<"]["<<j0<<"]=";
cin>>a[i0][j0];
a[j0][i0]=a[i0][j0];
}
afis_matrice();
st[0]=s;
}
voidtipar(intp)
{
intj;
for(j=1;j<=p;j++)
cout<<st[j]<<"";
30cout<<"\n";
}
intvalid(intp)
{inti,ok,i1,j1;
ok=1;
for(i=0;i<=p-1;i++)
if(st[p]==st[i])
ok=0;
if(a[st[p]][st[p-1]]==0)
ok=0;
returnok;
}
voidback(intp)
{intpval;
for(pval=1;pval<=n;pval++)
{st[p]=pval;
if(valid(p))
if(p==n&&a[st[p]][st[s]]==1)
{
cout<<"solutie=";
tipar(p);
}
elseback(p+1);
}
}
intmain()
{init();
back(1);
getch();}
I.12)Pătratemagice
Unpătratdelaturanestenumitmagicdacăesteformatdinnumereledela1la
n*nșisumapefiecarelinie,pefiecarecoloană,precumșipecele2diagonaleeste
constantă.Înplussecerecapeoricelinieșipeoricecoloană,sănuexistevaloriegale.
Exemplu:
Date.in
N=4
S=34
Date.out
121516
121435
137104
81169
31Algoritm:
#include<fstream>
#include<cstring>
usingnamespacestd;
ifstreamf("date.in");
ofstreamg("date.out");
intn,p[100],a[10][10],s,gata;
voidafis()
{
inti,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
g<<a[i][j]<<"";
g<<endl;
}
g<<endl;
gata=1;
}
intsumap(inti,intj)
{
ints=0,k;
for(k=1;k<=j;k++)s=s+a[i][k];
returns;
}
intsumal(inti)
{
ints=0,j;
for(j=1;j<=n;j++)s=s+a[i][j];
returns;
}
intsumac(intj)
{
ints=0,i;
for(i=1;i<=n;i++)s=s+a[i][j];
returns;
}
intsumad2()
{
ints=0,i;
for(i=1;i<=n;i++)s=s+a[i][n+1-i];
returns;
}
intsumad1()
32{
ints=0,i;
for(i=1;i<=n;i++)s=s+a[i][i];
returns;
}
intbun(inti,intj)
{
if(sumap(i,j)>s)return0;
if(j==n)if(sumal(i)!=s)return0;
if(i==n)if(sumac(j)!=s)return0;
if(i==n&&j==1)if(sumad2()!=s)return0;
if(i==n&&j==n)if(sumad1()!=s)return0;
return1;
}
voidback(inti,intj)
{
if(!gata)
for(intv=1;v<=n*n;v++)
if(!p[v])
{
a[i][j]=v;
p[v]=1;
if(bun(i,j))if(i==n&&j==n)afis();
elseif(j<n)back(i,j+1);
elseback(i+1,1);
p[v]=0;
}
}
intmain()
{
f>>n;
s=n*(n*n+1)/2;
gata=0;
back(1,1);
return0;
}
I.13)Problemalabirintului:
Unlabirintsecodificăprintr-omatricenxn.Elementeleacesteimatricesunt
numerotatecu0dacăestedrumblocat,1dacăpoatemergemaideparte.
Afișatidrumulprincareșoricelulpoatepărăsilabirintul.
33#include<stdio.h>
#defineN4
boolsolutie(
intlabirint[N][N],intx,
inty,intv[N][N]);
voidafiseaza(intv[N][N])
{
for(inti=0;i<N;i++){
for(intj=0;j<N;j++)
printf("%d",v[i][j]);
printf("\n");
}
}
boolsigur(intlabirint[N][N],intx,inty)
{
if(
x>=0&&x<N&&y>=0
&&y<N&&labirint[x][y]==1)
returntrue;
returnfalse;
}
boolsolutielabirint(intlabirint[N][N])
{
intv[N][N]={{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}};
if(solutie(
labirint,0,0,v)
==false){
printf("Nuarescapare");
returnfalse;
}
afiseaza(v);
returntrue;
}
boolsolutie(
intlabirint[N][N],intx,
inty,intv[N][N])
34{
if(
x==N-1&&y==N-1
&&labirint[x][y]==1){
v[x][y]=1;
returntrue;
}
if(sigur(labirint,x,y)==true){
v[x][y]=1;
if(solutie(
labirint,x+1,y,v)
==true)
returntrue;
if(solutie(
labirint,x,y+1,v)
==true)
returntrue;
v[x][y]=0;
returnfalse;
}
returnfalse;
}
intmain()
{
intlabirint[N][N]={{1,0,0,0},
{1,1,0,1},
{0,1,0,0},
{1,1,1,1}};
solutielabirint(labirint);
return0;
}
Cifra1aratădrumulșoriceluluiînlabirint
1000
1100
0100
0111
35I.14)Sărituracalului
Fiinddatăotablădeșahdedimensiuneanxnșiuncalîncolțulstângasusal
acesteia,seceresăseafișezetoateposibilitățiledemutareaacesteipiesedeșahastfel
încâtsătreacăosingurădatăprinfiecarepătrataltablei.Osoluțievafiafișatăcao
matricenxnîncaresuntnumerotatesăriturilecalului.
Pentrurezolvareaacesteiproblemevomcodificadirecțiilededeplasarepentrucăarfi
ineficientsăscriemdouăciclurifordela–2la2cucele25devariantededeplasare
dincarevalidesuntdoaropt.Deasemeneaaicispredeosebiredecelelalteprobleme
tratatelaaplicareametodeibacktrackingînplannuvomfolosiunvectorsoluție,ci
vomscriesăriturileîntablouurmărindcalareveniresărefacempozițiileocupate
pentruanuseluablocaje.Înfigurademaijossuntprezentatecele8mutăriposibile
pentruuncal.
#include<fstream>
#include<iostream>
usingnamespacestd;
constintdx[8]={-1,1,2,2,1,-1,-2,-2};
constintdy[8]={-2,-2,-1,1,2,2,1,-1};
inta[10][10],n;
ofstreamf("cal.out");
voidafis()
{inti,j;
for(i=1;i<=n;i++)
{for(j=1;j<=n;j++)f<<a[i][j]<<"";
f<<endl;
}
f<<endl;
}
intinside(inti,intj)
36{
returni>=1&&i<=n&&j>=1&&j<=n;
}
voidback(inti,intj,intpas)
{intk,inou,jnou;
a[i][j]=pas;
if(pas==n*n)afis();
elsefor(k=0;k<8;k++)
{inou=i+dx[k];
jnou=j+dy[k];
if(inside(inou,jnou)&&a[inou][jnou]==0)
back(inou,jnou,pas+1);
}
a[i][j]=0;
}intmain()
{cin>>n;
back(1,1,1);
}
Cal.outPrimeledouăsoluțiisunt:
12023341736
222716192433
7221263518
28156113225
37I.15)Sudoku
include<bits/stdc++.h>
usingnamespacestd;
#defineliber0
#defineN9
boolgasestelocliber(intmatrice[N][N],
int&lin,int&col);
boolisSafe(intmatrice[N][N],intlin,
intcol,intnum);
boolSolveSudoku(intmatrice[N][N])
{
intlin,col;
if(!gasestelocliber(matrice,lin,col))
returntrue;
for(intnum=1;num<=9;num++){
if(isSafe(matrice,lin,col,num)){
matrice[lin][col]=num;381330510
1429491231
12023341736
223316192427
7221263518
32156112825
381330510
1431491229
38if(SolveSudoku(matrice))
returntrue;
matrice[lin][col]=liber;
}
}
returnfalse;
}
boolgasestelocliber(intmatrice[N][N],
int&lin,int&col)
{
for(lin=0;lin<N;lin++)
for(col=0;col<N;col++)
if(matrice[lin][col]==liber)
returntrue;
returnfalse;
}
boolutilizatInlin(intmatrice[N][N],intlin,intnum)
{
for(intcol=0;col<N;col++)
if(matrice[lin][col]==num)
returntrue;
returnfalse;
}
boolutilizatInCol(intmatrice[N][N],intcol,intnum)
{
for(intlin=0;lin<N;lin++)
if(matrice[lin][col]==num)
returntrue;
returnfalse;
}
boolutilizatInpatratel(intmatrice[N][N],intpatratelStartlin,
intpatratelStartCol,intnum)
{
for(intlin=0;lin<3;lin++)
for(intcol=0;col<3;col++)
if(matrice[lin+patratelStartlin]
[col+patratelStartCol]
==num)
returntrue;
returnfalse;
}
boolisSafe(intmatrice[N][N],intlin,
39intcol,intnum)
{
return!utilizatInlin(matrice,lin,num)
&&!utilizatInCol(matrice,col,num)
&&!utilizatInpatratel(matrice,lin-lin%3,
col-col%3,num)
&&matrice[lin][col]==liber;
}
voidprintmatrice(intmatrice[N][N])
{
for(intlin=0;lin<N;lin++){
for(intcol=0;col<N;col++)
cout<<matrice[lin][col]<<"";
cout<<endl;
}
}
intmain()
{
intmatrice[N][N]={{0,0,0,9,1,0,4,0,7},
{3,0,4,6,8,0,0,1,0},
{0,7,9,0,5,0,6,0,3},
{9,0,2,0,0,0,8,0,1},
{0,1,5,0,0,6,3,4,0},
{0,3,0,0,9,0,0,5,0},
{2,0,0,5,3,0,7,0,0},
{0,0,3,1,0,0,0,9,0},
{6,0,0,4,7,0,1,3,0}};
if(SolveSudoku(matrice)==true)
printmatrice(matrice);
else
cout<<"NuexistasolutiepentruacestjocSudoku";
return0;
}
586913427
324687915
179254683
962345871
815726349
437891256
291538764
743162598
658479132
40CapitolulalII-lea:MetodaGreedy
AlgoritmiidetipGreedyseaplicaunorproblemedeoptimizareacăror
solutiepoatefiexprimatăsubformaunuivectordenumereîntregi(cuvaloriîntre1si
n).Într-oproblemădeoptimizaretrebuiegăsităsoluțiaoptimădintretoatesoluțiile
posibile.
MetodaGreedysepoateaplicaunorproblemedeoptimizare,caalternativă
maieficientălaocăutareexhaustivă(detip'backtracking').Spredeosebiredemetoda
Backtraking,metodaGreedynudispunedemecanismuluideîntoarcereșioferădoar
osoluție.
DescriereametodeiGreedy:
Pentrufiecareelementcareurmeazăsăfieadăugatsoluțieifinale,se
efectueazăoalegereasadinelementelemulțimiiA(dupăunmecanismspecific
fiecăreiproblemeînparte),iardacăesteposibil,acestaesteadăugat.Algoritmulse
terminăfiecândafostgăsităsoluțiacerută,fiecânds-aconstatatinexistențaacesteia.
Intuitiv,alegemunelement,aldoilea,….pânăcândobținemcedorimsaupânăcândau
fosttestatetoateelementelemulțimii.Deaiciprovinesinumelemetodei
(greedy=lacom).
TehnicaGreedyconducelatimpdecalculpolinomial.
II.1)Problemabanilor
PentruproblemaurmătoarevomfolosiunalgoritmGreedypentruagăsi
numărulminimdemonedesaubancnotepentruaputeaplătiosumădată.Trebuiesă
menționatcăsevorfolosimonedesaubancnotecareauvaloareaegalăcuunuldin
elementelemulțimii:{1,2,5,10,20,50,100,200,500,2000}șivatrebuisă
returnezenumărulmonedelorsaubancnotelorfolositepentruaplătisuma.
ÎnrezolvareaacesteiproblemecuajutorulmetodeiGreedy,vomcăuta
valoareamaximăauneibancnote/monedemaimicădecâtsumacaretrebuieplătităși
apoivomrealizadiferențadintresumășivaloareabancnoteișivomrepetaprocedeul
pânăcândsumaeste0.
#include<bits/stdc++.h>
usingnamespacestd;
intbancnote[]={1,2,5,10,20,50,100,200,500,2000};
intn=sizeof(bancnote)/sizeof(bancnote[0]);
voidschimb(intsum)
{
vector<int>monede;
for(inti=n-1;i>=0;i–){
while(sum>=bancnote[i]){
sum-=bancnote[i];
41monede.push_back(bancnote[i]);
}
}
for(inti=0;i<monede.size();i++)
cout<<monede[i]<<"\t";
}
intmain()
{
intn=7000;
cout<<"Minimuldebancnotepentruaplatisuma"<<n<<"este\t";
schimb(n);
return0;
}
II.2:Problema:Fracțiaegipteană
Oricefracțienm,cunm, ,poatefireprezentatăcasumădefracțiicareau
numărătorulegal1.OastfeldefracțieestecunoscutăsubnumeledeFracție
egipteană.
Exemplu:21
101
53
GenerămofracțieegipteanăfolosindalgoritmulGreedy.
#include<iostream>
usingnamespacestd;
voidegiptr(intm,intn)
{
if(n==0||m==0)
return;
if(n%m==0)
{
42cout<<"1/"<<n/m;
return;
}
if(n%m==0)
{
cout<<m/n;
return;
}
if(m>n)
{
cout<<m/n<<"+";
egiptr(m%n,n);
return;
}
intk=n/m+1;
cout<<"1/"<<k<<"+";
egiptr(m*k-n,n*k);
}
intmain()
{
intm=3,n=5;
cout<<"Fracția"
<<m<<"/"<<n<<"sescriecasumăastfel\n";
egiptr(m,n);
return0;
}
43II.3)ProblemaColorăriihărților
Sedăohartăcunțări.Găsițiosoluțiedecolorareahărții,utilizândcelmultpatru
culori,dacăoricaredouățărivecinesuntcoloratediferit.
Exemplu:
Dateintrare:Perechiledețărivecinedinharta1:
(0,1);
(0,2);
(1,2);
(1,3);
(2,3);
(3,4);
Perechiledețărivecinedinharta2:
(0,1);
(0,2);
(1,2);
(1,4);
(2,4);
(4,3);
Dateieșire:Coloreazăharta1
tara0areculoarea0
tara1areculoarea1
tara2areculoarea2
tara3areculoarea0
tara4areculoarea1
Coloreazăharta2
tara0areculoarea0
tara1areculoarea1
tara2areculoarea2
tara3areculoarea0
tara4areculoarea3
#include<iostream>
#include<list>
usingnamespacestd;
classGraf
{
intV;
list<int>*adiacenta;
public:
Graf(intV){this->V=V;adiacenta=newlist<int>[V];}
~Graf() {delete[]adiacenta;}
44voidadaugamuchie(intv,intw);
voidgreedyColor();
};
voidGraf::adaugamuchie(intv,intw)
{
adiacenta[v].push_back(w);
adiacenta[w].push_back(v);
}
voidGraf::greedyColor()
{
intculoare[V];
culoare[0]=0;
for(intu=1;u<V;u++)
culoare[u]=-1;
boolvalabil[V];
for(intcr=0;cr<V;cr++)
valabil[cr]=false;
for(intu=1;u<V;u++)
{
list<int>::iteratori;
for(i=adiacenta[u].begin();i!=adiacenta[u].end();++i)
if(culoare[*i]!=-1)
valabil[culoare[*i]]=true;
intcr;
for(cr=0;cr<V;cr++)
if(valabil[cr]==false)
break;
culoare[u]=cr;
for(i=adiacenta[u].begin();i!=adiacenta[u].end();++i)
if(culoare[*i]!=-1)
45valabil[culoare[*i]]=false;
}
for(intu=0;u<V;u++)
cout<<"tara"<<u<<"areculoarea"
<<culoare[u]<<endl;
}
intmain()
{
Grafg1(5);
g1.adaugamuchie(0,1);
g1.adaugamuchie(0,2);
g1.adaugamuchie(1,2);
g1.adaugamuchie(1,3);
g1.adaugamuchie(2,3);
g1.adaugamuchie(3,4);
cout<<"Coloreazaharta1\n";
g1.greedyColor();
Grafg2(5);
g2.adaugamuchie(0,1);
g2.adaugamuchie(0,2);
g2.adaugamuchie(1,2);
g2.adaugamuchie(1,4);
g2.adaugamuchie(2,4);
g2.adaugamuchie(4,3);
cout<<"\nColoreazaharta2\n";
g2.greedyColor();
return0;
}
II.4)Problema:Programareaspectacolelor
Într-ozisuntprogramatenspectacoledemuzică,iarpentrufiecaresecunoaște
momentuldeînceputșimomentuldesfârșit,exprimateprinnumerenaturale.Unelev
doreștesăurmăreascăcâtmaimultespectacoleînîntregime.
Determinaținumărulmaximdespectacolecarepotfiurmărite,fărăcaacesteasăse
suprapună.
Exemplu:
Dateintrare:
V={{1,4},{2,3},{3,6},{6,7},{5,7},{6,9}};
46Dateieșire:
Alegespectacolele:(2,3);(3,6);(6,7);
#include<bits/stdc++.h>
usingnamespacestd;
structspectacol
{
intinceput,sfarsit;
};
boolcompara(spectacols1,spectacols2)
{
return(s1.sfarsit<s2.sfarsit);
}
voidarataspecatolele(spectacolv[],intn)
{
sort(v,v+n,compara);
cout<<"Alegespectacolele:";
inti=0;
cout<<"("<<v[i].inceput<<","<<v[i].sfarsit<<");";
for(intj=1;j<n;j++)
{
if(v[j].inceput>=v[i].sfarsit)
{
cout<<"("<<v[j].inceput<<","
<<v[j].sfarsit<<");";
i=j;
}
}
}
intmain()
{
spectacolv[]={{1,4},{2,3},{3,6},{6,7},
{5,7},{6,9}};
intn=sizeof(v)/sizeof(v[0]);
arataspecatolele(v,n);
return0;}
47II.5)ProblemaComisvoiajorul
Unagentdevânzăritrebuiesăvizitezeunnumărndeorașeșisăseîntoarcăînorașul
deplecareastfelîncâtsănutreacădedouăoriprinacelașiloc.Determinațiuntrasu
delungimeminimăpecareîlpoaterealizaagentul,știindcăelcunoaștedrumurile
dintreorașeșidistanțeleacestora.
#include<fstream>
usingnamespacestd;
ifstreamfin("date.in");
ofstreamfout("date.out");
intx[100],pus[100],n,s;
inta[100][100];
voidcitire()
{
inti,j;
fin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
fin>>a[i][j];
}
voidscriere()
{for(inti=1;i<=n;i++)fout<<x[i]<<"";
fout<<endl<<s;
}
voidvoiajor(intk)
{ intmin=100000,imin;
for(inti=1;i<=n;i++)
if(!pus[i]&&a[x[k-1]][i]<min&&i!=x[k-1])
{
min=a[x[k-1]][i];
imin=i;
}
x[k]=imin;
pus[imin]=1;
s=s+a[x[k-1]][imin];
if(k==n)scriere();
elsevoiajor(k+1);
}
intmain()
{
citire();
x[1]=1;
48pus[1]=1;
voiajor(2);
fin.close();
fout.close();
return0;
}
II.6)ProblemaRucsacului(fracționară)
SeconsiderăcădispunemdeunrucsaccucapacitateaWsidenobiecte,
definitefiecarepringreutatesivaloare,cetrebuieintroduceinrucsac.Secereo
modalitatedeaumplerucsaculcuobiecte,astfelîncâtvaloareatotalăsăfiemaximă.
Esteposibilcaoricâteobiectesibucătidinobiectesăfieintroduse.
Dateintrare:fiecareobiectestedefinitprin(valoare,greutate)
arr[]={{60,10},{100,20},{120,30}}
Volumulrucsacul,V=50;
Dateieșire
Valoareamaximăesteegalăcu240careseobțineprinpunereaa10și20kgși2/3
fraction
din30kg.Decicostultotalvafi:60+100+(2/3)(120)=240
Înproblemafracționarăarucsaculputemîmpărțiunobiectpentruamaximiza
valoareatotalăarucsacului.
Orezolvarebrutăs-arobțineprintestareatuturorsubmulțimilorcudiferitefracții,dar
aceastăabordarearduramult.
OsoluțieeficientăesteaplicareaalgoritmulGreedy.Ideeadebazăestesăcalculăm
raportuldintrevaloareșigreutatepentrufiecareobiectșisălesortăm.
#include<bits/stdc++.h>
usingnamespacestd;
structobiect
{intvaloare,greutate;
obiect(intvaloare,intgreutate):valoare(valoare),greutate(greutate)
{}
};
boolcmp(structobiecta,structobiectb)
{doubler1=(double)a.valoare/a.greutate;
doubler2=(double)b.valoare/b.greutate;
returnr1>r2;
}
doublerucsacfractionar(intW,structobiectv[],intn)
{sort(v,v+n,cmp);
intcurgreutate=0;
doublefinalvaloare=0.0;
for(inti=0;i<n;i++)
49{
if(curgreutate+v[i].greutate<=W)
{
curgreutate+=v[i].greutate;
finalvaloare+=v[i].valoare;
}
else
{
intremain=W-curgreutate;
finalvaloare+=v[i].valoare*((double)remain/v[i].greutate);
break;
}
}
returnfinalvaloare;
}
intmain()
{
intW=50;
obiectv[]={{60,10},{100,20},{120,30}};
intn=sizeof(v)/sizeof(v[0]);
cout<<"Valoareamaximaobtinuta"
<<rucsacfractionar(W,v,n);
return0;
}
II.7)ProblemaHoțiișipolițiștii
Sedăunvectordelungimencareîndeplineșteurmătoarelecerințe:
1.Fiecareelementdinvectorconținefieunpolițist,fieunhoț
2.Fiecarepolițistpoatecapturaunsingurhoț
3.Unpolițistnupoatecapturaunhoțcareestesituatlakpozițiideel.
Trebuiesăgăsimnumărulmaximdehoțicapturați.
Exemplul1.
Dateintrare:v[]={'P','H','H','P','H'},
k=1.
Dateieșire:2.
Exemplul2.
Dateintrare:v[]={'H','H','P','P','H','P'},
50k=2.
Dateieșire:3.
Dateintrare:v[]={'P','H','P','H','H','P'},
k=3.
Dateieșire:3.
Numărulmaximdehoțicarepotfiprinșiesteegalcu2.Primulpolițistîl
prindepeprimulhoț,aldoileapolițistpoateprindealdoileasaualtreileahoț.
OsoluțieeficientăesteutilizareaalgoritmuluiGreedy.Uneledinproprietățile
algoritmuluiGreedypotfiînșelătoare.
Dacăîncercămsăutilizăm:Fiecarepolițistdinstângapoateprindecelmai
apropiathoț.Algoritmulfuncționeazăpentruexemplul3,darpentruexemplul2
eșuează.
Deasemenea,amputeaspune:Fiecarepolițistdinstângapoateprindecelmai
îndepărtathoț.Algoritmulfuncționeazăpentruexemplul2,dareșueazăpentru
exemplul3.
1.Notămcelmaimicindicepentrupolițișticup,iaralhoțilorcuh.
Realizeazăatribuirea.Dacăkhp ,atuncigăseștenoulpșih.
2.Altfelincrementeazămin(p,h)pentruurmătorulpșihgăsit.
3.Repetătoțipașiipânăcândurmătorulpsauhestegăsit.
4.Returneazănumăruldeatribuirifăcute.
#include<iostream>
#include<vector>
#include<cmath>
usingnamespacestd;
intpolhot(charv[],intn,intk)
{
intres=0;
vector<int>hot;
vector<int>pol;
for(inti=0;i<n;i++){
if(v[i]=='P')
pol.push_back(i);
elseif(v[i]=='H')
hot.push_back(i);
}
intl=0,r=0;
51while(l<hot.size()&&r<pol.size()){
if(abs(hot[l]-pol[r])<=k){
res++;
l++;
r++;
}
elseif(hot[l]<pol[r])
l++;
else
r++;
}
returnres;
}
intmain()
{intk,n;
charv1[]={'P','H','H','P','H'};
k=2;
n=sizeof(v1)/sizeof(v1[0]);
cout<<"Numărulmaximdehoticapturati:"
<<polhot(v1,n,k)<<endl;
charv2[]={'H','H','P','P','H','P'};
k=2;
n=sizeof(v2)/sizeof(v2[0]);
cout<<"Nrmaximdehotiprinsi:"
<<polhot(v2,n,k)<<endl;
charv3[]={'P','H','P','H','H','P'};
k=3;
n=sizeof(v3)/sizeof(v3[0]);
cout<<"Nrmaximdehotiprinsi"
<<polhot(v3,n,k)<<endl;
return0;
}
II.8)ProblemaRafturilor
Avândînvederelungimeapereteluiwșirafturilededouălungimimșin,
găsiținumărulfiecăruitipperaftcaretrebuieutilizatșispațiulgolrămasînsoluția
optimă,astfelîncâtspațiulgolsăfieminim.Ceamaimaredintreceledouărafturieste
preferatădeoarececostulesteminim.Cutoateacestea,costulestesecundarșiprima
prioritateesteminimizareaspațiuluigolpeperete.
Exemple:
Dateintrare:w=40m=3n=6
Dateieșire:351
1 39 4039 6533
52Dateintrare:w=29m=2n=3
Dateieșire:470
0 29 2929 7342
#include<bits/stdc++.h>
usingnamespacestd;
voidoptimizare(intperete,intm,intn)
{
intnrm=0,nrn=0,nrperete=perete;
intp=0,q=0,spatiu;
while(perete>=n){
p=perete/m;
spatiu=perete%m;
if(spatiu<=nrperete){
nrm=p;
nrn=q;
nrperete=spatiu;
}
q+=1;
perete=perete-n;
}
cout<<nrm<<""<<nrn<<""
<<nrperete<<endl;
}
intmain()
{
intperete=40,m=3,n=6;
optimizare(perete,m,n);
perete=29,m=2,n=3;
optimizare(perete,m,n);
return0;}
II.9)ProblemaSumaariilorunordreptunghiuri
Pentruunvectorvdelungimen,determinațisumatuturorariilormaximeaunor
dreptunghiuricaresepotformadinelementelorvectorului.Deasemenea,valoarea
unuielementdinvectorpoatescădeamaximcuvaloarea1.
Exemple:
Dateintrare:v={7,6,7,8,1,2,1,2}
Dateieșire:44
Explicație:Decisumaariilordreptunghiurilorcreateesteegalăcu: 44 2167
Pas1:Ordonămdescrescătorelementelevectorului
53Pas2:Primeledouăelementevorreprezentalungimileprimuluidreptunghi.Acest
estevalabildoardacăacestedimensiuniegalesauprimulelementestemaimarecu1
decâtceldealdoilea.
Pas3:Procedămlafelșipentrulățimiledreptunghiului.Ovariabilăvaverificadacă
pentruundreptunghiexistăceledouădimensiuni:lungimeașilățimea.
#include<bits/stdc++.h>
usingnamespacestd;
intariemaxim(intv[],intn)
{
sort(v,v+n,greater<int>());
intsuma=0;
boolt=false;
intn1;
for(inti=0;i<n;i++)
{
if((v[i]==v[i+1]||v[i]-
v[i+1]==1)&&(!t))
{
t=true;
n1=v[i+1];
i++;
}
elseif((v[i]==v[i+1]||
v[i]-v[i+1]==1)&&(t))
{
suma=suma+v[i+1]*n1;
t=false;
i++;
}
}
returnsuma;
}
intmain()
{
intv[]={7,6,7,8,1,2,1,3};
54intn=sizeof(v)/sizeof(v[0]);
cout<<ariemaxim(v,n);
return0;
}
II.10)ProblemaRezervărilorîncadrulunuihotel
UnmanagerdehotelvreasăobținăînavansNrezervăripecamerepentruurmătorul
sezon.HotelulsăuareKcamere.Rezervărileconținatâtdateledesosire,câtșidatele
deieșire.Elvreasăafledacăaresufiecientecameredisponibileînhotelpentrua
satisfacecererea.
Exemplu:
DateintrareSosiri:[135]
Iesiri:[268]
K:1
Dateieșire:False
Managerularenevoiecamăcardouăcameredinintervalulaldoileașialtreilea
săsesuprapună.
Ideeaestesăsalvămdateleintrărilorșialeieșirilorîntr-unvectorauxiliarcuun
aditionalmarkerpentruaindicadacăestetimpulpentruintraresauiesire.Acum
sortămvectorul.Observămvectorulsortat,șipentrufiecaresosirecreștemcu1
numărulrezervăriloractive,șipentrufiecareieșirescădemcu1.Mereutrebuie
analizatlanumărulmaximderezervăriactive.Dacănumărulmaximderezervări
activeestemaimaredecâtk,returnămfals,altfeladevărat.
#include<bits/stdc++.h>
usingnamespacestd;
boolrezervariposibile(intsosire[],
intplecare[],intn,intk)
{
vector<pair<int,int>>ans;
for(inti=0;i<n;i++){
ans.push_back(make_pair(sosire[i],1));
ans.push_back(make_pair(plecare[i],0));
}
sort(ans.begin(),ans.end());
intcurr_active=0,max_active=0;
for(inti=0;i<ans.size();i++){
55if(ans[i].second==1){
curr_active++;
max_active=max(max_active,
curr_active);
}
else
curr_active–;
}
return(k>=max_active);
}
intmain()
{
intsosire[]={1,3,7};
intplecare[]={2,6,8};
intn=sizeof(sosire)/sizeof(plecare[0]);
cout<<(rezervariposibile(sosire,plecare,n,1)?
"Yes\n"
:"No\n");
return0;
}
II.11)ProblemaOrdinealexicografică
Dându-seunvectorv,găsițivectorulcuvalorilecelemaimicidinpunctdevedere
lexicograf,carepoatefiobținutprinschimbuladouăelementevecine,prink
operațiideschimb.
Examples:
Dateintrare:arr[]={5,4,2,1,9}
k=3
Pas1:54129
Pas2:51429
Pas3:15429
Decidupăceletrei,interschimbări,vomobținevectorul:
15429
Dateintrare:arr[]={5,4,2,1,9}
k=5
Dateieșire:arr[]={1,2,5,4,9}
OabordareeficientăarfiaplicareaunuialgorimGreedy.
Primadată,alegemceamaimicăvaloaredinvector.Plasă,acestavaloarepeprima
pozițiedupăceammutatcelalaltevaloricucâteopoziție.Scădemnumărulde
56operațiideinterschimbare(k-1).Dacăk>0aplicămaceeașiprocedurăpentru
următoareleelementepânăk=0.
#include<bits/stdc++.h>
usingnamespacestd;
voidnrmininterschimbari(intv[],intn,intk)
{
for(inti=0;i<n-1&&k>0;++i)
{
intpos=i;
for(intj=i+1;j<n;++j)
{
if(j-i>k)
break;
if(v[j]<v[pos])
pos=j;
}
for(intj=pos;j>i;–j)
swap(v[j],v[j-1]);
k-=pos-i;
}
}
intmain()
{
intv[]={7,6,9,2,1};
intn=sizeof(v)/sizeof(v[0]);
intk=3;
nrmininterschimbari(v,n,k);
for(inti=0;i<n;++i)
cout<<v[i]<<"";
}
57II.12)ProblemaSarciniledelucru
Sedăunvectordesarcinidelucru,încarefiecaresarcinădelucruareuntermen
limitățiunprofitasociatdacăsarcinaesteterminatăînaintedetermen.
Deasemenea,seconsiderăcăfiecaresarcinadelucruareosingurăunitatedetimp,
decitermenulminimminimposibilpentruoricejobeste1.Cumsepoatemaximiza
profitultotaldacăpoatefiprogramatăcâteolucrarelaunmomentdat.
Exemple:
Dateintrare:următoarelepatrusarcinidelucru
SarcinaIdTermenlimităProfit
a 5 25
b 2 12
c 3 55
d 1 30
Dateieșire:Profitulestemaximdacăsuntrezolvatesarcinilecareauid-ul
b,c,a
#include<iostream>
#include<algorithm>
usingnamespacestd;
structsarcina
{
charid;
inttermen;
intprofit;
};
boolcomparare(sarcinaa,sarcinab)
{
return(a.profit>b.profit);
}
voidafisareorarsarcina(sarcinav[],intn)
{
sort(v,v+n,comparare);
intrezultat[n];
boolslot[n];
for(inti=0;i<n;i++)
slot[i]=false;
58CapitolulalIII-lea:DIVIDEETIMPERA
Cumînmatematicăexistămaimultemodalitățispecificedearezolvao
problemă,șiîninformaticăpentrumulteproblemegăsimrețetecareauroluldea
dirijaînalegereaceluimaibunalgoritmșiauneimetodedeaconstruiunalgoritm
eficient.
Expresia“Divideetimpera“provinedinlimbalatinășiîntraducere
înseamnă“dezbinășicucerește”.Principiulacestemetodeconstăînfaptulcăo
problemăpoatefirezolvată,dacăpoatefiîmpărțităînmaimulteproblemesimilarede
dimensiunimaimici.
Înprogramareprincipiulsepoatefaceastfel:sedescompuneproblemaîn
douăsaumaimulteproblemedeacelașitip.for(inti=0;i<n;i++)
{
for(intj=min(n,v[i].termen)-1;j>=0;j–)
{
if(slot[j]==false)
{
rezultat[j]=i;
slot[j]=true;
break;
}
}
}
for(inti=0;i<n;i++)
if(slot[i])
cout<<v[rezultat[i]].id<<"";
}
intmain()
{
sarcinav[]={{'a',5,25},{'b',2,12},{'c',3,55},
{'d',1,30}};
intn=sizeof(v)/sizeof(v[0]);
cout<<"Secventasarcinilordelucrupentruaobtineprofitmaximeste";
afisareorarsarcina(v,n);
return0;
}
59Acesteproblemepotfi:
1.elementare
2.neelementare.
Celeelementareserezolvădirect,iarceleneelementaresevorîmpărțiînaltedouă
tipurideproblemeelementareșineelementare,pânăcândseobțindoarprobleme
elementare.Menționămcăoperațiadedescompuneretrebuiesăgenereze
subproblemeindependente(acesteaprelucreazămulțimidisjunctealedatelorde
intrare).
Prinreconstituireașirecombinareasoluțiilorsubproblemelor,înordine
inversă,obținemsoluțiileproblemeiinițiale.AlgoritmulDivideetImperaeste
implementatrecursiv.
Numărulproblemelorcareserezolvăcuaceastămetodăestedestuldemic,
deoarecenuoriceproblemăpoatefidescompusărepetat.
DescriereametodeiDivideetImperaeste:
1.Împarte(divide)-împarteproblemaînproblememaimici
2.Cucerește(Conquer)-rezolvăsubproblemelerecursiv
3.Combină(combine)-combinărezultatele
Existăsituațiicândfazadecombinarearezultatelorlipsește.
Acestlucruseîntâmplăatuncicândsoluțiaproblemeiinițialeestesoluțiaunei
subproblemeobținutăînurmadescumpuneriisauesteconstruităsimultanînetapele
dedescompunere.
III.1)Problemă:Sumaelementelordintr-unvector
CuajutorulmetodeiDivideetImpera,realizațiofuncțiecaresădeterminesuma
elementelordintr-unvectordelungimen.Elementelevectoruluisuntnumereîntregi.
#include<iostream>
usingnamespacestd;
intsuma(intv[100],intl,intr)
{if(l==r)returnv[l];
elsereturnsuma(v,l,(l+r)/2)+suma(v,(l+r)/2+1,r);
}
intmain()
{
intv[100],n,i;
cin>>n;
for(i=1;i<=n;i++)cin>>v[i];
cout<<suma(v,1,n);
system("pause");
return0;
}
60III.2)Celmaimaredivizorcomun
CuajutorulmetodeiDivideetImpera,realizațiofuncțiecaresădetermine
celmaimaredivizorcomunalelementelorîntregidintr-unvectordelungimen.
Descriereaproblemei:
Citimdelimitărilevectoruluiprinindicii ),(rl.
Descompunemproblemainițială,îndouăsubproblemealecărorindicidevin ),(ml și
),1 (rm .Variabilamidentificăindicelemijloculuidinvectorulinițial.
Dacăllr ,soluțiaestecmmdc(rvlv, ).
Aceastăproblemăpoatefirezolvatăprinaplicareaproprietățiideasociativitatea
operațieicmmdc.
#include<iostream>
usingnamespacestd;
intv[100],n,x;
voidcitire()
{
cout<<"numaruldeelemente=";cin>>n;
cout<<"siruldeelemente\n";
for(inti=1;i<=n;i++)
{cout<<"v["<<i<<"]=";cin>>v[i];
}
}
intalgoritm(inta,intb)
{if(a==b)returna;
elseif(a>b)returnalgoritm(a-b,b);
elsereturnalgoritm(a,b-a);
}
intcmmdc(intp,intu)
{intm;
if(u-p==1)algoritm(v[p],v[u]);
else
if(p==u)returnv[p];
{
m=(p+u)/2;
returnalgoritm(cmmdc(p,m),cmmdc(m+1,u));
}}
intmain()
{
citire();
cout<<"cmmdc="<<cmmdc(1,n);
}
61III.3).Rădăcinadeordin3
#include<iostream>
usingnamespacestd;
doubleradcubica(doublex,doublea,doubleb)
{
if(b-a<=0.0001)returnb;
else
{doublem=(a+b)/2;
if(m*m*m<x)returnradcubica(x,m,b);
elsereturnradcubica(x,a,m);
}
}
intmain()
{doublex;
cin>>x;
if(x>0)if(x<1)cout<<radcubica(x,0,1);
elsecout<<radcubica(x,0,x);
elseif(x>-1)cout<<radcubica(x,-1,0);
elsecout<<radcubica(x,x,0);
system("pause");
return0;
}
18
2.26209
III.4)MergeSort
Pentruunvectorvdedimensiunen,realizațiunsubprogramcaresăimplementezeo
sortareprininterclasare.
Sedăunvectorrlv….SeîmpartevectorulvîndouăpărțișivomapelamSort
pentruasortafiecaresubvector,șifuncțiacombinapentruacontopiceidoisubvectori
sortați.
Dacărl,problemanumainecesităodescompunere,vectorulestedejasortat.
Interclasare(rmlv ,,, )estecheiaprocedeuluicareneasigurăcăvectoriimlv…și
rmv …1 dejasortați,sevorcombinapentruaformaunsingurvector.
Găseșteelementuldinmijlocpentruaîmpărțivectorulîndoisubvectori
Mijlocul 2/) (rlm
1.ApeleazămSort ),,(mlv
2.ApeleazămSort ),1 ,(rmv
3.Apeleazăcombina ),,,(rmlv
Vectorulinițial
623,0,5,67,12,7,9,15
Vectorsortat:
27915324567
#include<iostream>
usingnamespacestd;
voidinterschimbare(int&a,int&b)
{
intt;
t=a;
a=b;
b=t;}
voidafisare(int*v,intsize){
for(inti=0;i<size;i++)
cout<<v[i]<<"";
cout<<endl;}
voidcombina(int*v,intl,intm,intr){
inti,j,k,ns,nd;
ns=m-l+1;nd=r-m;
intsv[ns],dv[nd];
for(i=0;i<ns;i++)
sv[i]=v[l+i];
for(j=0;j<nd;j++)
dv[j]=v[m+1+j];
i=0;j=0;k=l;
while(i<ns&&j<nd){
if(sv[i]<=dv[j]){
v[k]=sv[i];
i++;
}else{
v[k]=dv[j];
j++;
}
k++;
}
while(i<ns){
v[k]=sv[i];
i++;k++;
}
while(j<nd){
v[k]=dv[j];
j++;k++;
}}
voidmSort(int*v,intl,intr){
intm;
if(l<r){
intm=l+(r-l)/2;
mSort(v,l,m);
mSort(v,m+1,r);
combina(v,l,m,r);
}}
63intmain()
{
intv1[]={3,0,5,67,12,7,9,15};
intn=sizeof(v1)/sizeof(v1[0]);
printf("Vectorulinitial:\n");
afisare(v1,n);
mSort(v1,0,n-1);
printf("\nVectorsortat:\n");
afisare(v1,n);
return0;
}
III.5)QuickSort
QuicksortesteunalgoritmcareprovinedinmetodaDivideetImpera.
Problemă:Pentruunvectorvdedimensiunen,realizațiunsubprogram
caresăimplementezealgoritmulQuikSort.
Considerămcăvectorulprincipal,careestedelimitatdeindiciilșir.
Ultimulelementdinvectorv,rv esteplasatînpozițiacorectănotatăcupoz,în
vectorulordonat..Toateelementeledinstângaelementulrvsuntmaimici,iarcele
dindreaptamaimari.
Problemasedescompuneîndouăsubproblemedelimitatedeindicii
)1 ,(pozl și ),1 (rpoz .Fiecareproblemăurmăreștesăsortezesubvectoruluipe
careîlprelucrează.
Dacărl,vectorulestedejasortat.
Problemaaresoluțiedoardacăpoatefiaplicatprocesulrecursivde
descompunerepânăcândobținemproblemeelementare.
#include<bits/stdc++.h>
usingnamespacestd;
voidschimba(int*a,int*b)
{
intt=*a;
*a=*b;
*b=t;
}
64intfunctie(intv[],intl,intr)
{
intpoz=v[r];
inti=(l-1);
for(intj=l;j<=r-1;j++)
{
if(v[j]<poz)
{
i++;
schimba(&v[i],&v[j]);
}
}
schimba(&v[i+1],&v[r]);
return(i+1);
}
voidqSort(intv[],intl,intr)
{
if(l<r)
{
intk=functie(v,l,r);
qSort(v,l,k-1);
qSort(v,k+1,r);
}
}
voidafisare(intv[],intsize)
{
inti;
for(i=0;i<size;i++)
cout<<v[i]<<"";
cout<<endl;
}
intmain()
{
intv[]={10,7,8,9,1,5};
intn=sizeof(v)/sizeof(v[0]);
qSort(a,0,n-1);
cout<<"Vectorsortateste:\n";
afisare(v,n);
65return0;}
Vectorulsortat:1,5,7,8,9,10
III.6)Căutareabinară
Pentruunvectordelungimensortatcrescătorrealizațiofuncțiecare
determinăpozițiaelementuluik.Dacăelementulknuaparținevectorului,atunci
returnează0.
Considerămcăvectorulprincipal,careestedelimitatdeindiciilșir.Problemapoate
fidescompusăîndouăsubproblemedelimitatedeintervalele )1,(ml și ),(rm .
Variabilamesteindiceledemijlocalvectoruluiprincipal.
Dacăxmv,soluțiaesteindicelem.
Dacămmvcăutareasevarealizaînprimulsubvector )1,(ml ,altfelseva
realizaîncelălaltsubvector.
Observămcăprinaceastămetodă,amredusproblemaprincipală,laoproblemăde
dimensiunemaimică.Vomaveadouăproblemededimensiuneredusă,daralgoritmul
sevaaplicadoarpentruuna.
Cuajutorulacesteimetode,găsimmultmaiușorintervalulîncaresegăseștesoluția,
decietapadecombinareasoluțiilordinceledouăintervalevalipsi.
#include<iostream>
usingnamespacestd;
intv[100],n,k;
voidcautbin(intl,intr)
{
intm=(l+r)/2;
if(k==v[m])
cout<<"pozitiaelementuluieste="<<m;
else
if(l<r)
if(k<v[m])
cautbin(l,m-1);
elsecautbin(m+1,r);
elsecout<<"nuafostgasit.";
}
intmain()
{
cout<<"n=";cin>>n;
for(inti=1;i<=n;i++)
{
cout<<"v["<<i<<"]=";cin>>v[i];
}
cout<<"k=";cin>>k;
cautbin(0,n);
return0;
}
66
40372615041 32 24 17
pozitiakvvvvvvvn
III.7)Sumaelementelorprimedintr-unvector
Determinaținumărulelementelorprimedinacestvectordelungimen.
6
012365
3
#include<iostream>
usingnamespacestd;
intv[100],n;
intverificareprim(intn)
{
if(n<=1)return0;
inti=2;
while(i<=n/2)
if(n%i==0)return0;
elsei++;
return1;
}
intimpartire(intl,intr)
{
intm,x;
if(l==r)
if(verificareprime(v[l])and(v[l]!=1))
return1;
elsereturn0;
else
{m=(l+r)/2;
returnimpartire(l,m)+impartire(m+1,r);;
}
}
intmain()
{
67cin>>n;
inti;
for(i=1;i<=n;i++)
cin>>v[i];
cout<<impartire(1,n);
}
CuajutprulmetodeialgoritmulDivideetimpera,săsecalculezesuma:
)1( …3221 nn S
Pentrun=20
Suma=3080
#include<iostream>
usingnamespacestd;
intn;
voidimparte(intl,intr,int&suma)
{
intm,suma1,suma2;
if(l==r)
termen=l*(l+1);
else
{m=(l+r)/2;
imparte(l,m,suma1);
imparte(m+1,r,suma2);
suma=suma1+suma2;
}
}
intmain()
{intsuma=0;
cin>>n;
imparte(1,n,suma);
cout<<suma;
}III.8)Sumaprodusdedoitermeniconsecutivi
68III.9)Metodabisectieiuneifunctiipeintervale
Sedăfuncția 300,300 :f , 1 7 5)(2 3xxxf .Determinațiosoluțiea
funcției 0)(xf peintervalul300,300 cuoeroarede610.
Dateieșire:Valoarearadaciniieste-0.339118.
#include<iostream>
usingnamespacestd;
#defineeroare0.000001
doublefunctie(doublex){
return5*x*x*x-7*x*x+1;
}
voidbisectiem(doublel,doubler){
if(functie(l)*functie(r)>=0){
cout<<"farasolutie\n";
return;
}
doublem=l;
while((r-l)>=eroare){
m=(l+r)/2;
if(functie(m)==0.0)
break;
elseif(functie(m)*functie(l)<0)
r=m;
else
b=m;
}
cout<<"solutiaeste"<<m;
}
intmain(){
doublel=-300,r=300;
bisectiem(l,r);
return0;
}
69Bibliografie:
1)MiloșescuMaria,Informatică.ManualpentruclasaaXI,EdituraDidactică
șiPedagogică,București,2006
2)MateescuD.M,MoraruP,Informaticăpentruliceușibacalaureat,Materia
declasaaIX-a,edituraDonaris,Sibiu2006
3)DanaLica,MirceaPasoi,FundamenteleProgramării,Culegerede
problemepentruclasaaXI-a,EdituraL&SSoft,2006
8)AdrianRunceanu,Metodeșitehnicideprogramare,EdituraAcademică
Brâncuși,2003
Site-uri
http://info.mcip.ro/?cap=Backtracking&prob=363
https://informaticacnet.wordpress.com/category/clasa-a-xi-a/metode-backtra
king/
http://ro.wikipedia.org/wiki/Backtracking
http://en.wikipedia.org/wiki/Backtracking
https://infoarena.ro/
https://www.pbinfo.ro/articole/16619/metoda-greedy
https://www.geeksforgeeks.org
https://info.mcip.ro
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Conf.univ.dr.DORUANASTASIUPOPESCU ABSOLVENT CRISTINACALACAN Pitești 2020 2UNIVERSITATEADINPITEȘTI FACULTATEADEȘTIINȚE,EDUCAȚIEFIZICĂȘIINFORMATICĂ… [611419] (ID: 611419)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
