Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*2.1 Fie o matrice MxN, unde fiecare element reprezinta o altitudine(practic, un plan 3D, cu altitudini discretizate).Se doreste sa se afle cantitatea de apa care va stoca acest plan in urma unei ploi.
- Pentru
- 2, 2, 2
- 2, 1, 2
- 2, 2, 2
- Se va returna 1
- Pentru
- 3 6
- 1 4 3 1 3 2
- 3 2 1 3 2 4
- 2 3 3 2 3 1
- Se va return 4
- 5 6
- 3 5 3 3 3 3
- 5 3 5 3 1 1
- 5 1 1 1 1 3
- 5 1 1 3 3 2
- 4 3 4 5 2 3
- se va returna 0
- */
- #include <iostream>
- #include <fstream>
- #include <algorithm>
- #define NMAX 6
- #define MAX 1000
- using namespace std;
- struct Coord
- {
- int i, j;
- };
- struct Pct
- {
- int val;
- int i, j;
- };
- int V[NMAX][NMAX];
- Coord vMisc[4] = { {-1,0},{0,1},{1,0},{0,-1} };
- Coord vPozitie[NMAX*NMAX];
- int vVizitat[NMAX][NMAX];
- void citire(int&, int&);
- void afisare(int, int);
- int logica(int, int);
- //cautare scurgeri din margine si umplerea lor
- int DFSmargine(int, int, bool&);
- void cautareDinMargineDFS(int, int, int, int, int&, const int&, int&, int&);
- void umplereDinMargine(int, int);
- //umplere goluri centrale si numarare
- void NumaraGoluri(int, int, int&, bool&);
- //vf
- bool interior(int, int, int, int);
- bool viz(int, int, int);
- int main()
- {
- int n, m;
- int suma = 0;
- citire(n, m);
- afisare(n, m);
- suma = logica(n, m);
- cout << "suma: " << suma;
- return 0;
- }
- int logica(int n, int m)
- {
- int s = 0;
- //nu mai sunt de numarat goluri
- bool suntGoluri = 1;
- while (suntGoluri)
- {
- suntGoluri = 0;
- DFSmargine(n, m, suntGoluri);
- NumaraGoluri(n, m, s, suntGoluri);
- }
- return s;
- }
- int DFSmargine(int n, int m, bool& suntGoluri)
- {
- //umplu marginile cu cel mai mic element mai mare decat cel de la care plec
- //loop pe toata marginea
- int i, j;
- int flag;
- int count;
- int min;
- //pct-ul de pe margine de unde intru
- Pct intrareM;
- //cate elem am gasit plecand dintr-o margine egale cu elem meu
- for (int j = 0; j < m; j++)
- {
- ///marginea superioara
- i = 0;
- //nr de poz in vect de pozitii
- count = 0;
- //flag daca am intalnit un element mai mic de cat cel din margine
- flag = 1;
- //cautareDinMargineDFS cu minimul gasit
- // minimul
- min = MAX;
- //refac vec de viz
- memset(vVizitat, 0, m*n * sizeof(vVizitat[0][0]));
- cautareDinMargineDFS(i, j, n, m, min, V[i][j], count, flag);
- if (flag)
- {
- umplereDinMargine(count, min);
- if (min == MAX)
- return 1;
- suntGoluri = 1;
- afisare(n, m);
- }
- ///marginea inferioara
- i = n - 1;
- //nr de poz in vect de pozitii
- count = 0;
- //flag daca am intalnit un element mai mic de cat cel din margine
- flag = 1;
- //cautareDinMargineDFS cu minimul gasit
- // minimul
- min = MAX;
- //refac vec de viz
- memset(vVizitat, 0, m*n * sizeof(vVizitat[0][0]));
- cautareDinMargineDFS(i, j, n, m, min, V[i][j], count, flag);
- if (flag)
- {
- umplereDinMargine(count, min);
- if (min == MAX)
- return 1;
- suntGoluri = 1;
- afisare(n, m);
- }
- }
- for (int i = 1; i < n - 1; i++)
- {
- ///laterala stanga
- j = 0;
- //nr de poz in vect de pozitii
- count = 0;
- //flag daca am intalnit un element mai mic de cat cel din margine
- flag = 1;
- //cautareDinMargineDFS cu minimul gasit
- // minimul
- min = MAX;
- //refac vec de viz
- memset(vVizitat, 0, m*n * sizeof(vVizitat[0][0]));
- cautareDinMargineDFS(i, j, n, m, min, V[i][j], count, flag);
- if (flag)
- {
- umplereDinMargine(count, min);
- if (min == MAX)
- return 1;
- suntGoluri = 1;
- afisare(n, m);
- }
- ///laterala dreapta
- j = m - 1;
- //nr de poz in vect de pozitii
- count = 0;
- //flag daca am intalnit un element mai mic de cat cel din margine
- flag = 1;
- //cautareDinMargineDFS cu minimul gasit
- // minimul
- min = MAX;
- //refac vec de viz
- memset(vVizitat, 0, m*n * sizeof(vVizitat[0][0]));
- cautareDinMargineDFS(i, j, n, m, min, V[i][j], count, flag);
- if (flag)
- {
- umplereDinMargine(count, min);
- if (min == MAX)
- break;
- suntGoluri = 1;
- afisare(n, m);
- }
- }
- return 1;
- }
- void cautareDinMargineDFS(int i, int j, int n, int m, int &min, const int& intrareVal, int& count, int& flag)
- {
- if (flag == 0)
- return;
- if (interior(i, j, n, m) && !viz(i, j, count))
- vVizitat[i][j] = 1;
- else
- return;
- //daca gasesc un minim mai mic decat elem initial ma intorc
- if (V[i][j] < intrareVal)
- {
- count = 0;
- flag = 0;
- return;
- }
- //daca e un elem mai mare decat cel de intrare
- //si mai mic decat min updatez minimul
- if (V[i][j] > intrareVal && V[i][j] < min)
- min = V[i][j];
- //daca este un element egal cu cel initial merg mai departe
- if (V[i][j] == intrareVal)
- {
- //il bag in vect de poz pt o umplere ulterioara
- vPozitie[count] = { i,j };
- //maresc count
- count++;
- //caut si in celelalte directii
- for (int dir = 0; dir < 4; dir++)
- {
- if (interior(i + vMisc[dir].i, j + vMisc[dir].j, n, m))
- {
- if (flag == 0)
- return;
- cautareDinMargineDFS(i + vMisc[dir].i, j + vMisc[dir].j, n, m, min, intrareVal, count, flag);
- }
- }
- }
- }
- void NumaraGoluri(int n, int m, int& s, bool& suntGoluri)
- {
- //aflu minim
- int minim = MAX;
- int maxim = -1;
- int i, j;
- for (j = 0; j < m; j++)
- {
- i = 0;
- if (V[i][j] < minim)
- minim = V[i][j];
- if (V[i][j] > maxim)
- maxim = V[i][j];
- i = n - 1;
- if (V[i][j] < minim)
- minim = V[i][j];
- if (V[i][j] > maxim)
- maxim = V[i][j];
- }
- for (int i = 1; i < n - 1; i++)
- {
- j = 0;
- if (V[i][j] < minim)
- minim = V[i][j];
- if (V[i][j] > maxim)
- maxim = V[i][j];
- j = m - 1;
- if (V[i][j] < minim)
- minim = V[i][j];
- if (V[i][j] > maxim)
- maxim = V[i][j];
- }
- if (maxim - minim == 0)
- suntGoluri = 0;
- for (int i = 0; i < n; i++)
- for (int j = 0; j < m; j++)
- {
- if (V[i][j] < minim)
- {
- //adaug golul la suma
- s += minim - V[i][j];
- //umplu golul
- V[i][j] = minim;
- }
- }
- }
- void umplereDinMargine(int count, int min)
- {
- for (int k = 0; k < count; k++)
- {
- V[vPozitie[k].i][vPozitie[k].j] = min;
- }
- }
- //check interior
- bool interior(int i, int j, int n, int m)
- {
- return (i >= 0 && i < n &&j >= 0 && j < m);
- }
- //check anterior vizitat
- bool viz(int i, int j, int count)
- {
- for (int k = 0; k < count; k++)
- {
- if (vVizitat[i][j] == 1)
- return true;
- }
- return false;
- }
- void citire(int&n, int&m)
- {
- ifstream fin("SD.in");
- fin >> n >> m;
- for (int i = 0; i < n; i++)
- for (int j = 0; j < m; j++)
- fin >> V[i][j];
- fin.close();
- }
- void afisare(int n, int m)
- {
- for (int i = 0; i < n; i++)
- {
- for (int j = 0; j < m; j++)
- cout << V[i][j] << " ";
- cout << endl;
- }
- cout << endl;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement