Sunteți pe pagina 1din 18

Programare Dinamică

Programare dinamică presupune rezolvarea unei probleme prin descompunerea ei în


subprobleme şi rezolvarea acestora. Spre deosebire de divide et impera, subproblemele
nu sunt disjuncte, ci se suprapun.

Pentru a evita recalcularea porțiunilor care se suprapun, rezolvarea se face pornind de la


cele mai mici subprobleme şi folosindu-ne de rezultatul acestora calculăm subproblema
imediat mai mare. Cele mai mici subprobleme sunt numite subprobleme unitare, acestea
putând fi rezolvate într-o complexitate constantă, ex: cea mai mare subsecvență dintr-o
mulțime de un singur element.

Pentru a nu recalcula soluțiile subproblemelor ce ar trebui rezolvate de mai multe ori, pe


ramuri diferite, se reține soluția subproblemelor folosind o tabelă (matrice uni, bi sau
multi-dimensională în funcție de problemă) cu rezultatul fiecărei subprobleme. Aceasta
tehnica se numește memoizare.

Aceasta tehnică determina ”valoarea” soluției pentru fiecare din subprobleme. Mergând
de la subprobleme mici la subprobleme din ce în ce mai mari ajungem la soluția optimă,
la nivelul întregii probleme. Motivul pentru care aceasta tehnica se numește Programare
Dinamică este datorată flexibilității ei, ”valoarea” schimbându-și înțelesul logic de la o
problema la alta. În probleme de minimizarea costului, ”valoarea” este reprezentata de
costul minim. In probleme care presupun identificarea unei componente maxime,
”valoarea” este caracterizată de dimensiunea componentei.

După calcularea valorii pentru toate subproblemele se poate determina efectiv mulțimea
de elemente care compun soluția. „Reconstrucția” soluţiei se face mergând din
subproblemă în subproblemă, începând de la problema cu valoarea optimă și ajungând în
subprobleme unitare. Metoda și recurența variază de la problemă la problemă, dar în
urma unor exerciții practice va deveni din ce în ce mai facil să le identificați.

Aplicând aceasta tehnică determinăm una din soluțiile optime, problema putând avea mai
multe soluții optime. În cazul în care se dorește determinarea tuturor soluțiilor optime,
algoritmul trebuie combinat cu unul de backtracking în vederea construcției soluțiilor.

Aplicarea acestei tehnici de programare poate fi descompusă în următoarea secvență de


pași:
1. Identificarea structurii și a metricilor utilizate în caracterizarea soluției optime;
2. Determinarea unei metode de calcul recursiv pentru a afla valoarea fiecărei
subprobleme;
3. Calcularea “bottom-up” a acestei valori (de la subproblemele cele mai mici la cele mai
mari);
4. Reconstrucția soluției optime pornind de la rezultatele obținute anterior.

Exemple de probleme
Programarea Dinamică este cea mai flexibilă tehnica din programare. Cel mai ușor mod
de a o înțelege presupune parcurgerea cât mai multor exemple.

O problema clasică de Programare Dinamică este determinarea celui mai lung subșir
strict crescător dintr-un șir de numere. Un subșir al unui șir este format din caractere (nu
neapărat consecutive) ale șirului respectiv, în ordinea în care acestea apar în șir.

Exemplu: pentru șirul 24 12 15 15 8 19 răspunsul este șirul 12 15 19

Se observa că dacă încercăm o abordare greedy nu putem stabili nici măcar elementul de
început într-un mod corect. Totuși, problema se poate rezolva ”muncitorește” folosind un
algoritm care alege toate combinațiile de numere din șir, validează că șirul obținut este
strict crescător şi îl reține pe cel de lungime maximă, dar aceasta abordare are
complexitatea temporală O(2N). Cu optimizări este posibil sa se ajungă la O(N!).

O metoda de rezolvare mai eficientă folosește Programarea Dinamică. Începem prin a


stabili pentru fiecare element lungimea celui mai lung subșir strict crescător care începe
cu primul element și se termină în elementul respectiv. Numim aceasta valoare besti și
aplicăm formula recursivă besti = 1 + max(bestj), cu j<i și elemj < elemi.

Aplicând acest algoritm obținem:

elem 24 12 15 15 8 19
best 1 1 2 2 1 3

Pentru 24 sau 12 nu există nici un alt element în stânga lor strict mai mici decât ele, de
aceea au best egal cu 1. Pentru elementele 15 se poate găsi în stânga lor 12 strict mai mic
decât ele. Pentru 19 se găsește elementul 15 strict mai mic decât el. Cum 15 deja este
capăt pentru un subșir soluție de 2 elemente, putem spune că 19 este capătul pentru un
subșir soluție de 3 elemente.

Cum pentru fiecare element din mulțime trebuie să găsim un element mai mic decât el şi
cu best maxim, avem o complexitate O(N) pentru fiecare element. În total rezultă o
complexitate O(N2). Se pot obține şi rezolvări cu o complexitate mai mica folosind
structuri de date avansate. Atât soluția în O(N2), cât si o soluție în O(N log N) poate fi
găsită la [5]. Tot acolo se poate găsi și o lista de probleme mai dificile ce folosesc tehnica
Programării Dinamice, adaptată în diferite forme.

Pentru a găsi care sunt elementele ce alcătuiesc subșirul strict crescător putem să reținem
și o „cale de întoarcere”. Reconstrucția astfel obținută are complexitatea O(N). Exemplu:
subproblema care se termina în elementul 19 are subșirul de lungime maximă 3 şi a fost
calculată folosind subproblema care se termină cu elementul 15 (oricare din ele). Subșirul
de lungime maximă care se termină în 15 a fost calculat folosindu-ne de elementul 12. 12
marchează sfârșitul reconstrucției fiind cel mai mic element din subșir.
O altă problemă cu o aplicare clasică a Programării Dinamice este şi determinarea celui
mai lung subșir comun a două șiruri de caractere. Descrierea problemei, indicații de
rezolvare şi o modalitate de evaluare a soluțiilor voastre poate fi găsită la [6].

O problema care admite o varietate mare de soluții este cea a subsecvenței de sume
maxime. Enunțul poate fi găsit la [7]

1. O tabla de sah se citeste ca o matrice n*n in care pozitiile libere au valoarea 0, iar
piesele sunt marcate prin valoarea 1.
Pe prima linie pe coloana js se afla un pion. Sa se determine drumul pe care poate
ajunge pionul pe ultima linie luand un numar maxim de piese.
Pozitia initiala a pionului se considera libera.
Pionul aflat in pozitia i,j se poate deplasa astfel:
- in pozitia i+1,j daca e libera
- in pozitia i+1, j-1 daca e piesa in aceasta pozitie
- in pozitia i+1, j+1 daca e piesa in aceasta pozitie

Exemplu:
53
00000
01010
01111
00011
01011

Drumul optim este:


13
22
33
44
55
Pe acest drum pionul ia 4 piese.
#include<fstream>
using namespace std;
ifstream fin("pion.in");
ofstream fout("pion.out");
int n,i,j, a[50][50], c[50][50],b[50][50],is,js;
void citire()
{ int i,j;
fin>>n>>js;
is=1;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) fin>>a[i][j];
}
void pd()
{ int i,j;
b[is][js]=1;
for(i=2;i<=n;i++)
{
for(j=1;j<=n;j++)
{ if(a[i][j]==0)
{ if(b[i-1][j]>0) { c[i][j]=c[i-1][j]; b[i][j]=1; }
}
else if(c[i-1][j-1]>c[i-1][j+1])
{
if(b[i-1][j-1]>0) {c[i][j]=c[i-1][j-
1]+1;b[i][j]=1; }
else if(b[i-1][j+1]>0) {c[i][j]=c[i-1]
[j+1]+1;b[i][j]=1; }
}
else {
if(b[i-1][j+1]>0) {c[i][j]=c[i-1]
[j+1]+1;b[i][j]=1; }
else if(b[i-1][j-1]>0) {c[i][j]=c[i-1][j-
1]+1;b[i][j]=1; }
}
}
}
}
void drum(int i, int j)
{
if(i==1) fout<<i<<" "<<j<<endl;
else { if(a[i][j]==0) drum(i-1,j);
else if(c[i-1][j-1]+1==c[i][j])
drum(i-1,j-1);
else drum(i-1,j+1);
fout<<i<<" "<<j<<endl;
}
}
void afis()
{
int max=0,jm;
for(j=1;j<=n;j++) if(c[n][j]>max) { max=c[n][j]; jm=j; }
fout<<max<<endl;
drum(n,jm);
}

int main()
{ citire();
pd();
afis();
fin.close();
fout.close();
return 0;
}

2. In fisierul m.in se afla pe prima linie un numar natural n cel mult 20000,iar pe
liniile urmatoare o matrice patratica de dimensiune n care contine doar elemente 0
si 1.
Sa se determine cel mai mare patrat care contine doar valori 1. Se for afisa in
fisierul text m.out urmatoarele valori separate prin spatiu: latura patratului, linia si
coloana coltului stanga sus al patratului. Daca exista mai mult astfel de patrate se
va afisa doar cel mai de sus.
Exemplu:
5
11000
11101
11111
11100
10111
Se afiseaza 3 2 1
#include<fstream>
using namespace std;

int n, a[3][20001],maxx,im,jm;
ifstream fin("m.in");
ofstream fout("m.out");

void Read();
void Write();

int main()
{
Read();
Write();
fin.close();
fout.close();
return 0;
}

void Read()
{ int i,j,m,x;
fin>>n;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{ fin>>x;
if(i==1) a[i][j]=x;
else
{ if(x==0) a[2][j]=0;
else if(j==1) a[2][j]=x;
else
{
m=a[1][j-1];
if(a[1][j]<m) m=a[1][j];
if(a[2][j-1]<m) m=a[2][j-1];
a[2][j]=m+1;
if(a[2][j]>maxx) { maxx=a[2][j];
im=i;
jm=j;
}
}
}
a[1][j-1]=a[2][j-1];
}
a[1][n]=a[2][n];
}
}

void Write()
{ fout<<maxx<<" "<<im-maxx+1<<" "<<jm-maxx+1;
}

3. Se dau n(n+1)/2 numere naturale aranjate intr-un triunghi format din elementele
de sub si de pe diagonala unei matrici patratice de ordin n.
Se calculeaza sume pornind din elementul de pe prima linie prin deplasari in
vecinii de sub si din dreapta. Gasiti suma maxima care se poate calcula astfel si
care sunt valorile din care se obtine suma maxima.
Exemplu:
n=4
2
35
634
5614
suma maxima este 17
si se obtine din valorile 2 3 6 6
#include <fstream>
using namespace std;
ifstream fin ("date.in");
ofstream fout ("date.out");

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


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

void drum(int n, int a[100][100], int s[100][100], int i, int j)


{
if(i>1)
{
if(s[i][j]-s[i-1][j-1]==a[i][j]) drum (n,a,s,i-1,j-1);
else drum (n,a,s,i-1,j);
fout<<a[i][j]<<" ";
}
else fout<<a[1][1]<<" ";
}

int main()
{
int i,j,a[100][100],n,s[100][100],maxx;
citire(n,a);
s[1][1]=a[1][1];
for(i=2;i<=n;i++)
for(j=1;j<=i;j++)
if(j==1) s[i][j]=s[i-1][j]+a[i][j];
else if(j==i) s[i][j]=s[i-1][j-1]+a[i][j];
else if(s[i-1][j]<s[i-1][j-1]) s[i][j]=a[i][j]+s[i-1][j-
1];
else s[i][j]=a[i][j]+s[i-1][j];

maxx=0;
int mj;
for(j=1;j<=n;j++) if(s[n][j]>maxx) { maxx=s[n][j]; mj=j;}
fout<<maxx<<endl;
drum(n,a,s,n,mj);
fin.close();
fout.close();
return 0;
}
4. Se citeste o matrice patratica de ordin n formata din numere naturale.
Se calculeaza sume pornind de pe prima linie prin deplasari in vecinii de sub si
din dreapta. Gasiti suma maxima care se poate calcula astfel si care sunt valorile
din care se obtine suma maxima.
Exemplu:
n=4
7158
3561
6348
5614
suma maxima este 23
si se obtine din valorile 5 6 8 4
#include <fstream>
using namespace std;
ifstream fin ("date.in");
ofstream fout ("date.out");

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


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

void drum(int n, int a[100][100], int s[100][100], int i, int j)


{
if(i>0)
{
if(s[i][j]-s[i-1][j-1]==a[i][j]) drum (n,a,s,i-1,j-1);
else drum (n,a,s,i-1,j);
fout<<a[i][j]<<" ";
}
}

int main()
{
int i,j,a[100][100],n,s[100][100],maxx;
citire(n,a);
for(j=1;j<=n;j++) s[1][j]=a[1][j];
for(i=2;i<=n;i++)
for(j=1;j<=n;j++)
if(j==1) s[i][j]=s[i-1][j]+a[i][j];
else if(s[i-1][j]<s[i-1][j-1]) s[i][j]=a[i][j]+s[i-1][j-
1];
else s[i][j]=a[i][j]+s[i-1][j];
maxx=0;
int mj;
for(j=1;j<=n;j++) if(s[n][j]>maxx) { maxx=s[n][j]; mj=j;}
fout<<maxx<<endl;
drum(n,a,s,n,mj);
fin.close();
fout.close();
return 0;
}

5. Se citeste o matrice patratica de ordin n formata din numere naturale.


Se calculeaza sume pornind de pe prima linie prin deplasari pe linia urmatoare in
unul dintre cei 3 vecini de pe aceeasi coloana sau de pe cele 2 alaturate. Gasiti
suma maxima care se poate calcula astfel si care sunt valorile din care se obtine
suma maxima.
Exemplu:
n=4
8158
3561
6348
5614
suma maxima este 26
si se obtine din valorile 8 6 8 4
#include <fstream>
using namespace std;
ifstream fin ("date.in");
ofstream fout ("date.out");

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


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

void drum(int n, int a[100][100], int s[100][100], int i, int j)


{
if(i>0)
{
if(s[i][j]-s[i-1][j+1]==a[i][j]) drum (n,a,s,i-1,j+1);
else if(s[i][j]-s[i-1][j-1]==a[i][j]) drum (n,a,s,i-1,j-1);
else drum (n,a,s,i-1,j);
fout<<a[i][j]<<" ";
}
}

int main()
{
int i,j,a[100][100]={0},n,s[100][100]={0},maxx;
citire(n,a);
for(j=1;j<=n;j++) s[1][j]=a[1][j];
for(i=2;i<=n;i++)
for(j=1;j<=n;j++)
if(s[i-1][j]<=s[i-1][j-1] && s[i-1][j+1]<=s[i-1][j-1]) s[i]
[j]=a[i][j]+s[i-1][j-1];
else if(s[i-1][j]>=s[i-1][j-1] && s[i-1][j]>=s[i-1]
[j+1]) s[i][j]=a[i][j]+s[i-1][j];
else s[i][j]=a[i][j]+s[i-1][j+1];

maxx=0;
int mj;
for(j=1;j<=n;j++) if(s[n][j]>maxx) { maxx=s[n][j]; mj=j;}
fout<<maxx<<endl;
drum(n,a,s,n,mj);
fin.close();
fout.close();
return 0;
}

6. Calculati cate submultimi cu k elemente are o multime cu n elemente.


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

int main()
{
unsigned long int a[500][500]={0};
int i,j,k,n;
fin>>n>>k;
a[0][0]=1;
for(i=1;i<=n;i++)
for(j=0;j<=i;j++)
if(j==0 || j==i) a[i][j]=1;
else a[i][j]=a[i-1][j]+a[i-1][j-1];

fout<<a[n][k]<<endl;
fin.close();
fout.close();
return 0;
}

7. Un paianjen a tesut o panza de forma dreptunghiulara formata din n linii


orizontale si m linii verticale.
Calculati in cate moduri poate el merge din coltul stanga-sus in coltul dreapta-jos
facand un numar minim de pasi. (n+m-2)
Exemple:
pentru n=3 si m=3 exista 6 moduri
pentru n=1 si m=5 exista un singur mod

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

int main()
{
unsigned long int a[500][500]={0};
int i,j,m,n;
fin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(i==1 || j==1) a[i][j]=1;
else a[i][j]=a[i-1][j]+a[i][j-1];

fout<<a[n][m]<<endl;
fin.close();
fout.close();
return 0;
}

8. Se citeste un numar natural n si apoi un vector cu n elemente numere intregi.


Determinati secventa din vector care are suma elementelor maxima.
Exemplu:
n=9
-2 1 -3 3 -1 4 -6 2 3
secventa de suma maxima este 3 -1 4 si are suma 6
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");

int main()
{
int n,i,a[10000],s[10000]={0},maxx,im,jm;
fin>>n;
for(i=1;i<=n;i++)
fin>>a[i];
maxx = a[1];
for(i=1;i<=n;i++)
{
s[i]=a[i];
if(s[i]<s[i-1]+a[i]) s[i]=s[i-1]+a[i];
if(s[i]>maxx)
{ maxx=s[i];
jm=i;
}
}
fout<<maxx<<endl;
im=jm;
while(im>0 && s[im]>=0) im--;
im++;
for(i=im;i<=jm;i++) fout<<a[i]<<" ";
return 0;
}

9. Subsir crescator maximal.


Se citeste un numar n si apoi un sir de n numere intregi. Gasiti cel mai lung subsir
al sirului citit care are proprietatea ca elementele sunt in ordine crescatoare.
Daca exista mai multe subsiruri de lungime maxima se va afisa unul dintre ele.
Exemplu:
date.in
9
423052698
date.out
23569
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int n, A[10000], L[10000], maxt, pm;

void afis(int k, int m)


{
if(m>0)
{
int i=k-1;
while(L[i]!=m-1) i--;
afis(i,m-1);
fout<<A[k]<<" ";
}
}

int main()
{
int i,j,maxx;
fin>>n;
for(i=1;i<=n;i++) fin>>A[i];
L[1]=1;
for(i=2;i<=n;i++)
{
maxx=0;
for(j=1;j<i;j++)
if(A[j]<=A[i] && L[j]>maxx) maxx=L[j];
L[i]=maxx+1;
if(L[i]>maxt)
{
maxt=L[i];
pm=i;
}
}
afis(pm,maxt);
return 0;
}

10. Se citeste un numar n si apoi 2 siruri formate din cate n cuvinte fiecare. Primul sir
de cuvinte stabileste ordinea initiala, iar al doilea este o permutare a primului
(aceleasi cuvinte, dar in alta ordine).
Gasiti cel mai lung subsir de cuvinte din cel de-al doilea sir care are proprietatea
ca are cuvintele in ordinea din primul sir de cuvinte. Se va afisa numarul maxim
de cuvinte si apoi cuvintele.
Daca exista mai multe subsiruri de lungime maxima se va afisa unul dintre ele.
Exemplu:
date.in
5
platon kant marx stalin havel
marx stalin kant platon havel
date.out
3
marx stalin havel
#include <fstream>
#include <cstring>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int n, A[10000], L[10000], maxt, pm;
char O[10000][50], S[10000][50];

void citire()
{
int i;
fin>>n;
for(i=1;i<=n;i++) fin>>O[i];
for(i=1;i<=n;i++) fin>>S[i];
}

int poz(int k)
{
int i;
for(i=1;i<=n;i++)
if(strcmp(O[i],S[k])==0) return i;
return 0;
}

void afis(int k, int m)


{
if(m>0)
{
int i=k-1;
while(L[i]!=m-1) i--;
afis(i,m-1);
fout<<O[A[k]]<<" ";
}
}

int main()
{
int i,j,maxx;
citire();
for(i=1;i<=n;i++) A[i]=poz(i);
L[1]=1;
for(i=2;i<=n;i++)
{
maxx=0;
for(j=1;j<i;j++)
if(A[j]<=A[i] && L[j]>maxx) maxx=L[j];
L[i]=maxx+1;
if(L[i]>maxt)
{
maxt=L[i];
pm=i;
}
}
fout<<maxt<<endl;
afis(pm,maxt);
return 0;
}
11. O tabla de sah se citeste ca o matrice n*n in care pozitiile libere au valoarea 0, iar
piesele sunt marcate prin valoarea 1.
Sa se determine drumul pe care poate ajunge un pion de pe prima linie pe ultima
linie luand un numar maxim de piese. Pe prima linie nu sunt piese si pionul poate
porni din orice pozitie de pe prima linie
Pozitia initiala a pionului se considera libera.
Pionul aflat in pozitia i,j se poate deplasa astfel:
- in pozitia i+1,j daca e libera
- in pozitia i+1, j-1 daca e piesa in aceasta pozitie
- in pozitia i+1, j+1 daca e piesa in aceasta pozitie

Exemplu:
5
00000
01010
01111
00011
01011

Drumul optim este:


11
22
33
44
55
Pe acest drum pionul ia 4 piese.
#include<fstream>
using namespace std;
ifstream fin("pion.in");
ofstream fout("pion.out");
int n,i,j, a[50][50], c[50][50];
void citire()
{ int i,j;
fin>>n;
is=1;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) fin>>a[i][j];
}
void pd()
{ int i,j;
for(i=2;i<=n;i++)
for(j=1;j<=n;j++)
if(a[i][j]==0) c[i][j]=c[i-1][j];
else if(c[i-1][j-1]>c[i-1][j+1]) c[i][j]=c[i-1][j-
1]+1;
else c[i][j]=c[i-1][j+1]+1;

}
void drum(int i, int j)
{
if(i==1) fout<<i<<" "<<j<<endl;
else { if(a[i][j]==0) drum(i-1,j);
else if(c[i-1][j-1]+1==c[i][j])
drum(i-1,j-1);
else drum(i-1,j+1);
fout<<i<<" "<<j<<endl;
}
}
void afis()
{
int max=0,jm;
for(j=1;j<=n;j++) if(c[n][j]>max) { max=c[n][j]; jm=j; }
fout<<max-1<<endl;
drum(n,jm);
}

int main()
{ citire();
pd();
afis();
fin.close();
fout.close();
return 0;
}

12. Cladirea Finantelor publice este formata din birouri dispuse intr-un dreptunghi cu
nXm elemente. Intre doua birouri se poate trece daca sunt alaturate pe linie sau pe
coloana.
Pentru fiecare birou se cunoaste valoare taxei care trebuie platita in acel birou
(valoare naturala). Un contribuabil intra in cladire prin biroul 1,1 si trebuie sa o
parareasca prin biroul n,m. Calculati suma minima a taxelor pe care le poate plati
contribuabilul de la intrare pana la iesirea din cladire.
Exemplu:
n=4, m=3, dispunerea birourilor si taxa din fiecare:
372
643
631
622
Valoarea minima pe care o poate plati contribuabilul este 18 (corespunde
parcurgerii birourilor cu taxele: 3 7 2 3 1 2)
#include<fstream>
using namespace std;
ifstream fin ("date.in");
ofstream fout ("date.out");

int main()
{
int a[100][100],s[100][100]={0};
int i,j,m,n;
fin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
fin>>a[i][j];
if(i==1 && j==1) s[i][j]=a[i][j];
else if(i==1) s[i][j]=s[i][j-1]+a[i][j];
else if(j==1) s[i][j]=s[i-1][j]+a[i][j];
else if(s[i-1][j]<s[i][j-1]) s[i][j]=s[i-1][j]
+a[i][j];
else s[i][j]=s[i][j-1]+a[i][j];
}

fout<<s[n][m]<<endl;
fin.close();
fout.close();
return 0;
}

13. Se da o matrice patratica de ordin n care contine numere naturale si care are liniile
si coloanele numerotate de la 1 la n. Se citeste apoi un numar natural m si n
perechi de pozitii din matrice de forma (i1, j1) si (i2,j2) astfel incat i1 sa fie mai
mic decat i2 si j1 sa fie mai mic decat j2.
Calculati si afisati pentru fiecare pereche de pozitii suma elementelor din matrice
aflate in submatricea care are coltul stanga-sus in (i1,j1) si coltul dreapta-jos in
(i2,j2).
Exemplu:
date.in
3
121
361
136
3
2233
2133
1113
date.out
16 20 4
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int b[500][500];
int main()
{
int n,m,i,j,k,l,c;
fin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{ fin>>b[i][j];
b[i][j]=b[i][j]+b[i-1][j]+b[i][j-1]-b[i-1][j-1];
}
fin>>m;
for(k=0;k<m;k++)
{
fin>>i>>j>>l>>c;
fout<<b[l][c]-b[i-1][c]-b[l][j-1]+b[i-1][j-1]<<" ";
}
fin.close();
fout.close();
return 0;
}

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