Metoda DIVIDE ET IMPERA

Download Report

Transcript Metoda DIVIDE ET IMPERA

Metoda DIVIDE
ET IMPERA
Prezentarea metodei
Metoda Divide et Impera este o metodă generală
de programare ce constă în împărţirea repetată a
unei probleme de dimensiune mare în două sau
mai multe subprobleme de acelaşi tip, urmată de
combinarea soluţiilor subproblemelor rezolvate
pentru a obţine soluţia problemei propuse.
Exemplu
Se presupune că se dă secvenţa ak, ak+1,...,ap pentru o
anumită prelucrare şi că există m astfel încât kmp.
Prelucrarea secvenţei ak, ak+1,...,ap se realizează astfel:
- se prelucrează secvenţa ak, ak+1,...,am
- se prelucrează secvenţa am, am+1,...,ap
- se combină rezultatele pentru obţinerea prelucrării
dorite a secvenţei ak, ak+1,...,ap.
k
k+1
ak ak+1
m
p
am
ap
În continuare se prezintă o funcţie recursivă pentru
prelucrarea secvenţei ak, ak+1,...,ap, funcţie numită
Prelucrare şi are trei parametri:
- k indică începutul secvenţei ce trebuie prelucrată
- p indică sfârşitul secvenţei care trebuie prelucrată
- r indică rezultatul prelucrării.
void Prelucrare(k,p,r)
{
if(k-p<eps)
Prelucreaza(k,p,r)
else
{
Imparte(k,p,m)
Prelucrare(k,m,r1)
Prelucrare(m+1,p,r2)
Combina(r1,r2,r)
}
}
În funcţia de mai sus s-au folosit:
- eps – lungimea minimă a unei secvenţe ak,
- ak+1,...,ap notată prescurtat (k,p) pentru care
prelucrarea se poate face direct, fără a mai fi
necesară împărţirea în subprobleme
- funcţia Prelucrează realizează prelucrarea
secvenţelor de acest tip, furnizând rezultatul în r.
- funcţia Împarte determină subsecvenţele (k,m) şi
(m+1,p) în care se împarte secvenţa (k,p) şi furnizează
pe m
- funcţia Combină realizează combinarea rezultatelor
r1 şi r2 ale prelucrării a două secvenţe vecine (k,m) şi
(m+1,p) obţinând rezultatul r al prelucrării secvenţei
(k,p).
Problemă rezolvată
Să se scrie un program care, folosind Divide et Impera returnează 1+2+...+n.
Funcţii de tip 1
Orice sumă este o adunare de termeni T1+T2+...+Tn care se notează cu
S(1,n). Pentru a calcula sume de acest fel se realizează o funcţie care
permite calcularea sumei termenilor cu indici între k şi p adică permite
calcularea sumei Tk+Tk+1+...+Tp care se notează S(k,p).
Funcţia are doi parametri:
k - indicele de început adică indicele primului termen
p – indicele de sfârşit adică indicele ultimului termen
Funcţia returnează un rezultat întreg sau real şi se procedează astfel:
- dacă suma este un singur termen (k==p) suma este egală cu acel
termen Tk.
- dacă trebuie adunaţi mai mulţi termeni se procedează astfel:
Tk  ...  T
- se calculează suma din prima jumătate
( k p
 k  p
S  k ,  ) şi se
  2 
 2 


notează
T k  p   ...
- se calculează suma din a doua jumătate
(  Tp
1
k  p

S   ) şi
 1se
, p 
 2 

notează
 2 


- suma finală se obţine din adunarea celor două sume
Altfel spus:
Tk , daca k  p


 
, altfel
Tk  ...  Tp  
 T  ...  T
  T
 ...  Tp 
k p   k p
 k

 2 

 1


   2 


Ţinând cont de notaţie, se poate scrie:
Tk

S k , p      k  p     k  p 




, altfel
S
k,

s

1
,
p
   2   2 
 


  
Funcţia corespunzătoare formulei de mai sus este:
int S(int k, int p)
{
if(k==p) return k
else return S(k,(k+p)/2)+S((k+p)/2+1,p)
}
Programele sunt:
Functii de tip 1
#include<iostream.h>
int S(int k, int p)
{
if(k==p) return k;
else return S(k,(k+p)/2)+S((k+p)/2+1,p);
}
int main(void)
{
int n;
cout<<"dati n:";
cin>>n;
cout<<"Suma primelor "<<n<<" numere naturale
este "<<S(1,n);
}
Funcţii de tip 2
#include<iostream.h>
void Suma(int k, int p, int &S)
{
int S1,S2;
if(k==p) S=k;
else
{
Suma(k,(k+p)/2,S1);
Suma((k+p)/2+1,p,S2);
S=S1+S2;
}
}
void main()
{
int n,S;
cout<<"dati n:";
cin>>n;
Suma(1,n,S);
cout<<S;
}