Skip to content

Towers ​

Written by Iyed Baassou

English
Arabic
Arabic (Algeria)
French

1. Multi-source BFS ​

The first step is to compute the distance from every cell to its nearest tower.

  • Push all towers into a queue initially.
  • Perform BFS to fill dist[x][y] with the minimum distance from (x, y) to any tower. This gives us, for each cell, how “safe” it is.

2. Binary Search on the Answer ​

We want the maximum minimum distance along a valid path. This can be solved with binary search:

  • Let mid be a candidate minimum distance.
  • Check if there exists a path from V to J using only cells where dist[x][y] >= mid.
  • If yes, try a larger mid. Otherwise, try smaller.

The search range is from 0 to n + m (worst-case maximum Manhattan distance).

3. Checking the correctness (BFS again) ​

To test if a candidate mid works:

  • Start BFS from V if its distance to the nearest tower is at least mid.
  • Only move to cells with dist[x][y] >= mid.
  • If we can reach J, then mid is feasible.

Code ​

cpp
#include <bits/stdc++.h>
using namespace std;

int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};

int main() {
    int n, m; cin >> n >> m;

    vector<vector<char>> grid(n, vector<char>(m));
    vector<vector<int>> dist(n, vector<int>(m, INT_MAX));

    queue<pair<int,int>> q;
    int sx, sy, ex, ey;

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> grid[i][j];
            if (grid[i][j] == '+') q.push({i, j}), dist[i][j] = 0;
            if (grid[i][j] == 'V') sx = i, sy = j;
            if (grid[i][j] == 'J') ex = i, ey = j;
        }
    }

    while (!q.empty()) {
        auto [x, y] = q.front(); q.pop();

        for (int k = 0; k < 4; ++k) {
            int nx = x + dx[k], ny = y + dy[k];
            
            if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
            
            if (dist[nx][ny] > dist[x][y] + 1) {
                dist[nx][ny] = dist[x][y] + 1;
                q.push({nx, ny});
            }
        }
    }

    int l = 0, r = n + m, ans = 0;
    while (l <= r) {
        int mid = (l + r) / 2;

        vector<vector<int>> vis(n, vector<int>(m, 0));
        while (!q.empty()) q.pop();

        if (dist[sx][sy] >= mid) {
            vis[sx][sy] = 1;
            q.push({sx, sy});
        }

        int ok = 0;
        while (!q.empty()) {
            auto [x, y] = q.front(); q.pop();
            
            if (x == ex && y == ey) {
                ok = 1;
                break;
            }
            
            for (int k = 0; k < 4; k++) {
                int nx = x + dx[k], ny = y + dy[k];
            
                if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
            
                if (!vis[nx][ny] && dist[nx][ny] >= mid) {
                    vis[nx][ny] = 1;
                    q.push({nx, ny});
                }
            }
        }

        if (ok) l = mid + 1;
        else r = mid - 1;
    }

    cout << l - 1 << "\n";

    return 0;
}

Complexity ​

  • Multi-source BFS:
  • Each feasibility check BFS:
  • Binary search tries at most values.

Overall: , obviously enough for .