Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <stack>
- #include <set>
- using namespace std;
- class Map {
- private:
- int N, M;
- vector<vector<int> > heights;
- vector<vector<pair<int, int> > > sink;
- int dx[4]; // Смещения по x для соседей
- int dy[4]; // Смещения по y для соседей
- public:
- Map(int n, int m) {
- N = n;
- M = m;
- heights.resize(N, vector<int>(M));
- sink.resize(N, vector<pair<int, int> >(M, make_pair(-1, -1)));
- // Инициализация смещений: вверх, вниз, влево, вправо
- dx[0] = -1; dy[0] = 0; // Вверх
- dx[1] = 1; dy[1] = 0; // Вниз
- dx[2] = 0; dy[2] = -1; // Влево
- dx[3] = 0; dy[3] = 1; // Вправо
- }
- void read_heights() {
- for (int i = 0; i < N; ++i) {
- for (int j = 0; j < M; ++j) {
- cin >> heights[i][j];
- }
- }
- }
- bool is_valid(int x, int y) {
- return x >= 0 && x < N && y >= 0 && y < M;
- }
- pair<int, int> flow(int x, int y) {
- if (sink[x][y].first != -1) {
- return sink[x][y];
- }
- // Маркируем ячейку как обрабатываемую
- sink[x][y] = make_pair(-2, -2);
- // Список клеток текущего региона
- vector<pair<int, int> > region_cells;
- stack<pair<int, int> > s;
- vector<vector<bool> > visited(N, vector<bool>(M, false));
- s.push(make_pair(x, y));
- while (!s.empty()) {
- pair<int, int> current = s.top();
- s.pop();
- int cx = current.first;
- int cy = current.second;
- if (visited[cx][cy]) {
- continue;
- }
- visited[cx][cy] = true;
- region_cells.push_back(make_pair(cx, cy));
- for (int dir = 0; dir < 4; ++dir) {
- int nx = cx + dx[dir];
- int ny = cy + dy[dir];
- if (is_valid(nx, ny) && heights[nx][ny] == heights[cx][cy]) {
- s.push(make_pair(nx, ny));
- }
- }
- }
- // Поиск соседей с меньшей высотой
- pair<int, int> min_neighbor = make_pair(-1, -1);
- int min_height = 10001; // Максимальная высота + 1
- for (size_t i = 0; i < region_cells.size(); ++i) {
- int cx = region_cells[i].first;
- int cy = region_cells[i].second;
- for (int dir = 0; dir < 4; ++dir) {
- int nx = cx + dx[dir];
- int ny = cy + dy[dir];
- int neighbor_height;
- if (is_valid(nx, ny)) {
- neighbor_height = heights[nx][ny];
- } else {
- neighbor_height = 10001; // Высота за пределами карты
- }
- if (neighbor_height < heights[cx][cy]) {
- if (neighbor_height < min_height) {
- min_height = neighbor_height;
- min_neighbor = make_pair(nx, ny);
- }
- }
- }
- }
- pair<int, int> sink_coord;
- if (min_neighbor.first != -1 && is_valid(min_neighbor.first, min_neighbor.second)) {
- sink_coord = flow(min_neighbor.first, min_neighbor.second);
- } else if (min_neighbor.first != -1) {
- // Если сосед вне границ карты (высота 10001), то вода не может утечь
- sink_coord = make_pair(-1, -1);
- } else {
- // Это место является водосбором
- sink_coord = make_pair(x, y);
- }
- // Устанавливаем sink для всех клеток региона
- for (size_t i = 0; i < region_cells.size(); ++i) {
- int cx = region_cells[i].first;
- int cy = region_cells[i].second;
- sink[cx][cy] = sink_coord;
- }
- return sink[x][y];
- }
- int calculate_min_drains() {
- set<pair<int, int> > unique_sinks;
- for (int i = 0; i < N; ++i) {
- for (int j = 0; j < M; ++j) {
- pair<int, int> sink_coord = flow(i, j);
- if (sink_coord == make_pair(i, j)) {
- unique_sinks.insert(sink_coord);
- }
- }
- }
- return unique_sinks.size();
- }
- };
- int main() {
- int N, M;
- cin >> N >> M;
- Map terrain(N, M);
- terrain.read_heights();
- int result = terrain.calculate_min_drains();
- cout << result << endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement