Clasa a XII-a · Algoritmi pe grile: Lee și fillRead in English
Fill — numărul de zone în C++
În engleză: Flood fill: the number of regions
Ideea
Matricea are n linii și m coloane, cu 1 pentru teren și 0 pentru apă. O zonă este un grup maxim de celule 1 legate prin laturi (sus, jos, stânga, dreapta). Parcurgem matricea; la prima celulă 1 nevizitată dintr-o zonă numărăm o zonă nouă și pornim „umplerea”: funcția recursivă fill marchează celula cu 0 și se apelează pentru cei 4 vecini. Bordăm matricea cu 0, ca să nu ieșim din ea. Fiecare celulă este marcată o singură dată.
Descrierea în engleză
The matrix has n rows and m columns, with 1 for land and 0 for water. A region is a maximal group of 1 cells connected through their sides (up, down, left, right). We walk the matrix; at the first unvisited 1 cell of a region we count a new region and start 'filling': the recursive function fill marks the cell with 0 and calls itself for the 4 neighbours. We border the matrix with 0s so we never step outside it. Every cell is marked only once.
- Complexitate
- O(n * m)
- Clasa
- Clasa a XII-a (Grade 12)
Exemple
Intrare
4 5 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 1 0 1 1 0
Ieșire așteptată
4
Intrare
2 2 0 0 0 0
Ieșire așteptată
0
Codul C++
Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.
/*
* Titlu: Fill — numărul de zone
* Clasa: 12
* Capitol: Algoritmi pe grile: Lee și fill
* Descriere: Matricea are n linii și m coloane, cu 1 pentru teren și 0 pentru apă.
* O zonă este un grup maxim de celule 1 legate prin laturi (sus, jos,
* stânga, dreapta). Parcurgem matricea; la prima celulă 1 nevizitată
* dintr-o zonă numărăm o zonă nouă și pornim „umplerea”: funcția
* recursivă fill marchează celula cu 0 și se apelează pentru cei 4
* vecini. Bordăm matricea cu 0, ca să nu ieșim din ea. Fiecare celulă
* este marcată o singură dată.
* Complexitate: O(n * m)
*
* Exemplu
* Intrare:
* 4 5
* 1 1 0 0 1
* 1 0 0 1 1
* 0 0 1 0 0
* 1 0 1 1 0
* Ieșire: 4
*
* Exemplu
* Intrare:
* 2 2
* 0 0
* 0 0
* Ieșire: 0
*/
#include <iostream>
using namespace std;
const int DIM = 102; // n, m <= 100, plus bordura
int a[DIM][DIM];
int dl[4] = {-1, 0, 1, 0}; // deplasările pe linie: sus, dreapta, jos, stânga
int dc[4] = {0, 1, 0, -1}; // deplasările pe coloană
void fill(int i, int j)
{
a[i][j] = 0; // marcăm celula ca vizitată
for (int d = 0; d < 4; d++)
{
int iv = i + dl[d], jv = j + dc[d];
if (a[iv][jv] == 1)
fill(iv, jv);
}
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
// Liniile 0 și n + 1, coloanele 0 și m + 1 rămân 0 (variabilă globală): bordura.
int zone = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (a[i][j] == 1)
{
zone++;
fill(i, j);
}
cout << zone << '\n';
return 0;
}
Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.