Prilično je jasno da se zadatak može rešiti tako što se prebroje komponente povezanosti u grafu koji gradimo na osnovu podataka o lavirintu, međutim, prvo treba na pravi način definisati taj graf. Jedan način je da svaki kvadrat u lavirintu podelimo na četiri oblasti i da svaka oblast predstavlja jedan čvor grafa (taj graf ima \(4mn\) čvorova).
Oblasti u jednom kvadratu su povezane, osim ako je postavljena neka živa ograda.
Mogući su prelasci i iz jednog u drugi kvadrat.
Na narednoj slici prikazana je povezanost oblasti u lavirintu koji se opisuje karakterima:
/\/ /
Odgovarajući graf je prikazan na narednoj slici.
Pošto kvadrata ima \(m \times n\), čvorova grafa ima \(4 \times m \times n\). Svaki čvor je povezan sa najviše \(3\) druga čvora, pa je ukupna složenost prebrojavanja komponenti \(O(mn)\).
// svakom polju odgovaraju ima 4 čvora grafa
enum deo {GORE=0, DOLE, LEVO, DESNO};
// obilazak grafa zadatog nizom stringova od cvora sa koordinatama (v0, k0, d0)
// to je cvor u vrsti v0, koloni k0 i delu d0
// poseceni cvorovi su određeni visedimenzionim nizom posecen
void dfs(const vector<string>& linije, int m, int n,
bool>>>& posecen,
vector<vector<vector<int v0, int k0, int d0) {
// na steku cuvamo koordinate cvorova grafa
int, int, int>> s;
stack<tuple<
s.emplace(v0, k0, d0);true;
posecen[v0][k0][d0] =
while (!s.empty()) {
// skidamo koordinate tekuceg cvora sa steka
int v, k, d;
tie(v, k, d) = s.top(); s.pop();
// odredjujemo susede tekuceg cvora (ima ih najvise 3)
int, int, int>> susedi;
vector<tuple<// analiziramo polozaj tekuceg cvora u njegovom polju
switch(d) {
case GORE:
// levi i desni cvor tekuceg polja (ako nisu zaklonjeni preprekama)
if (linije[v][k] != '\\')
susedi.emplace_back(v, k, LEVO);if (linije[v][k] != '/')
susedi.emplace_back(v, k, DESNO);// donji cvor polja iznad (ako to polje postoji)
if (v > 0)
1, k, DOLE);
susedi.emplace_back(v-break;
case DOLE:
// levi i desni cvor tekuceg polja (ako nisu zaklonjeni preprekama)
if (linije[v][k] != '/')
susedi.emplace_back(v, k, LEVO);if (linije[v][k] != '\\')
susedi.emplace_back(v, k, DESNO);// gornji cvor polja ispod (ako to polje postoji)
if (v < m-1)
1, k, GORE);
susedi.emplace_back(v+break;
// ...
}
// prolazimo kroz niz suseda tekuceg cvora
for (const auto& t : susedi) {
int vv, kk, dd;
tie(vv, kk, dd) = t;// neposecene susede stavljamo na stek
if (!posecen[vv][kk][dd]) {
true;
posecen[vv][kk][dd] =
s.push(t);
}
}
}
}
int main() {
// ucitavamo crtez lavirinta
int m, n;
cin >> m >> n;
string s;
getline(cin, s);
vector<string> linije(m);
string linija;for (int i = 0; i < m; i++)
getline(cin, linije[i]);
// alociramo vektor posecenosti cvorova
// na pocetku nije posecen ni jedan cvor
bool>>> posecen;
vector<vector<vector<
posecen.resize(m);for (int i = 0; i < m; i++) {
posecen[i].resize(n);for (int j = 0; j < n; j++)
4, false);
posecen[i][j].resize(
}
// odredjujemo komponente povezanosti grafa i ispisujemo njihov broj
int brojOblasti = 0;
for (int v = 0; v < m; v++)
for (int k = 0; k < n; k++)
for (int d = GORE; d <= DESNO; d++)
if (!posecen[v][k][d]) {
dfs(linije, m, n, posecen, v, k, d);
brojOblasti++;
}
cout << brojOblasti << endl;return 0;
}
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <tuple>
using namespace std;
// svakom polju odgovaraju ima 4 čvora grafa
enum deo {GORE=0, DOLE, LEVO, DESNO};
// obilazak grafa zadatog nizom stringova od cvora sa koordinatama (v0, k0, d0)
// to je cvor u vrsti v0, koloni k0 i delu d0
// poseceni cvorovi su određeni visedimenzionim nizom posecen
void dfs(const vector<string>& linije, int m, int n,
bool>>>& posecen,
vector<vector<vector<int v0, int k0, int d0) {
// na steku cuvamo koordinate cvorova grafa
int, int, int>> s;
stack<tuple<
s.emplace(v0, k0, d0);true;
posecen[v0][k0][d0] =
while (!s.empty()) {
// skidamo koordinate tekuceg cvora sa steka
int v, k, d;
tie(v, k, d) = s.top(); s.pop();
// odredjujemo susede tekuceg cvora (ima ih najvise 3)
int, int, int>> susedi;
vector<tuple<// analiziramo polozaj tekuceg cvora u njegovom polju
switch(d) {
case GORE:
// levi i desni cvor tekuceg polja (ako nisu zaklonjeni preprekama)
if (linije[v][k] != '\\')
susedi.emplace_back(v, k, LEVO);if (linije[v][k] != '/')
susedi.emplace_back(v, k, DESNO);// donji cvor polja iznad (ako to polje postoji)
if (v > 0)
1, k, DOLE);
susedi.emplace_back(v-break;
case DOLE:
// levi i desni cvor tekuceg polja (ako nisu zaklonjeni preprekama)
if (linije[v][k] != '/')
susedi.emplace_back(v, k, LEVO);if (linije[v][k] != '\\')
susedi.emplace_back(v, k, DESNO);// gornji cvor polja ispod (ako to polje postoji)
if (v < m-1)
1, k, GORE);
susedi.emplace_back(v+break;
case LEVO:
// donji i gornji cvor tekuceg polja (ako nisu zaklonjeni preprekama)
if (linije[v][k] != '/')
susedi.emplace_back(v, k, DOLE);if (linije[v][k] != '\\')
susedi.emplace_back(v, k, GORE);// desni cvor polja levo (ako to polje postoji)
if (k > 0)
1, DESNO);
susedi.emplace_back(v, k-break;
case DESNO:
// donji i gornji cvor tekuceg polja (ako nisu zaklonjeni preprekama)
if (linije[v][k] != '\\')
susedi.emplace_back(v, k, DOLE);if (linije[v][k] != '/')
susedi.emplace_back(v, k, GORE);// levi cvor polja desno (ako to polje postoji)
if (k < n-1)
1, LEVO);
susedi.emplace_back(v, k+break;
}
// prolazimo kroz niz suseda tekuceg cvora
for (const auto& t : susedi) {
int vv, kk, dd;
tie(vv, kk, dd) = t;// neposecene susede stavljamo na stek
if (!posecen[vv][kk][dd]) {
true;
posecen[vv][kk][dd] =
s.push(t);
}
}
}
}
int main() {
// ucitavamo crtez lavirinta
int m, n;
cin >> m >> n;
string s;
getline(cin, s);
vector<string> linije(m);
string linija;for (int i = 0; i < m; i++)
getline(cin, linije[i]);
// alociramo vektor posecenosti cvorova
// na pocetku nije posecen ni jedan cvor
bool>>> posecen;
vector<vector<vector<
posecen.resize(m);for (int i = 0; i < m; i++) {
posecen[i].resize(n);for (int j = 0; j < n; j++)
4, false);
posecen[i][j].resize(
}
// odredjujemo komponente povezanosti grafa i ispisujemo njihov broj
int brojOblasti = 0;
for (int v = 0; v < m; v++)
for (int k = 0; k < n; k++)
for (int d = GORE; d <= DESNO; d++)
if (!posecen[v][k][d]) {
dfs(linije, m, n, posecen, v, k, d);
brojOblasti++;
}
cout << brojOblasti << endl;return 0;
}