Open In App

Minimizing water collection distance in Geek’s village

Last Updated : 04 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Geek’s village is represented by a 2-D matrix of characters of size n*m, where

H – Represents a house
W – Represents a well
. – Represents an open ground
N – Prohibited area(Not allowed to enter this area)

Every house in the village needs to take the water from the well, as the family members are so busy with their work, so every family wants to take the water from the well in minimum time, which is possible only if they have to cover as less distance as possible. Your task is to determine the minimum distance that a person in the house should travel to take out the water and carry it back to the house.

A person is allowed to move only in four directions left, right, up, and down. That means if he/she is the cell (i, j), then the possible cells he/she can reach in one move are (i, j-1), (i, j+1), (i-1, j), (i+1, j), and the person is not allowed to move out of the grid.

Note: For all the cells containing ‘N’, ‘W’, and ‘.’ our answer should be 0, and for all the houses where there is no possibility of taking water our answer should be -1.

Examples:

Input: n = 3, m = 3, c[][]: {{H, H, H}, {H, W, H}, {H, H, H}}
Output:
4 2 4 
2 0 2 
4 2 4
Explanation: There is only one well hence all the houses present in the corner of the matrix will have to travel a minimum distance of 4, 2 is for house to well and other two is for well to house. And the rest of the houses have to travel a minimum distance of 2 (House -> Well -> House).

Input: n = 5, m = 5, c[][]: {{H, N, H, H, H}, {N, N, H, H, W}, {W, H, H, H, H}, {H, H, H, H, H}, {H, H, H, H, H}}
Output:
-1 0 6 4 2 
0 0 4 2 0 
0 2 4 4 2 
2 4 6 6 4 
4 6 8 8 6
Explanation: There is no way any person from the house in cell (0, 0) can take the water from any well, and for the rest of the houses there is the same type of strategy we have to follow as followed in example 1. 

Approach: To solve the problem follow the below idea:

  • The idea to use BFS to traverse the village and calculate the distances from the well to each house.The BFS algorithm can be used to traverse this graph starting from the well, and it will visit all the cells reachable from the well in increasing order of their distance from the well. 
  • By maintaining a distance array, where the distance of each cell is initialized to a large value, and updating the distance of each cell whenever a shorter path is found, we can find the minimum distance from the well to each house. 
  • The BFS algorithm ensures that we explore all the reachable cells in a systematic manner, guaranteeing that we find the shortest path to each house.

Follow the steps to solve the problem:

  • Create an empty queue q and a boolean matrix v of size n x m to keep track of the visited cells. Also, create an integer matrix ans of size n x m to store the minimum distance from the well to each cell.
  • Initialize all the elements of ans to Integer. MAX_VALUE and all the elements of v to false.
  • Iterate through the 2D matrix c and find the cell containing the well. Mark this cell as visited in v, set its distance in ans to 0, and add it to the queue q as a pair object containing its row, column, and distance.
  • Define two arrays dx and dy containing the horizontal and vertical directions of movement, respectively, as {-1, 0, 1, 0} and {0, 1, 0, -1}.
  • While the queue q is not empty, remove the first element from the queue as a pair object p.
  • For each of the four directions of movement, calculate the row and column of the neighbor cell using nx = p.a + dx[i] and ny = p.b + dy[i], where i is the index of the current direction.
  • Check if the neighbor cell is inside the grid (i.e., nx ≥ 0 && nx < n && ny ≥ 0 && ny < m), not already visited (i.e., !v[nx][ny]), and not a prohibited cell (i.e., c[nx][ny] != ‘N’).
  • If the above conditions are met, mark the neighbor cell as visited in v, set its distance in ans to p.c + 1, and add it to the end of the queue q as a pair object containing its row, column, and distance (q.add(new pair(nx, ny, p.c + 1))).
  • After the BFS traversal is complete, iterate through the ans matrix again and update the distance of each cell as follows:
    • If the cell contains an obstacle (i.e., c[i][j] == ‘N’), set its distance to 0.
    • If the cell is open ground or the well (i.e., c[i][j] == ‘.’ || c[i][j] == ‘W’), set its distance to 0.
    • If the cell was not reachable from the well, set its distance to -1.
    • Otherwise, double the distance of the cell (i.e., ans[i][j] *= 2).
  • Return the ans matrix as the output.

Below is the implementation for the above approach:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
vector<vector<int> > chefAndWells(int n, int m,
                                  vector<vector<char> >& c)
{
    vector<vector<int> > res(n, vector<int>(m, 1e9));
    queue<pair<int, int> > q;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (c[i][j] == 'W') {
                q.push({ i, j });
                res[i][j] = 0;
            }
        }
    }
    int dx[4] = { 0, 0, -1, 1 };
    int dy[4] = { -1, 1, 0, 0 };
    while (q.size()) {
        auto cur = q.front();
        q.pop();
        int curx = cur.first, cury = cur.second;
        for (int i = 0; i < 4; i++) {
            int x = curx + dx[i], y = cury + dy[i];
            if (x >= 0 and x < n and y >= 0 and y < m
                and c[x][y] != 'N'
                and res[x][y] > res[curx][cury] + 1) {
                q.push({ x, y });
                res[x][y] = res[curx][cury] + 1;
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (c[i][j] == '.')
                res[i][j] = 0;
            else if (res[i][j] == 1e9 and c[i][j] != 'N')
                res[i][j] = -1;
            else if (res[i][j] == 1e9 and c[i][j] != 'H')
                res[i][j] = 0;
            else
                res[i][j] *= 2;
        }
    }
    return res;
}
 
// Drivers code
int main()
{
 
    int n = 3, m = 3;
    vector<vector<char> > c = { { 'H', 'H', 'H' },
                                { 'H', 'W', 'H' },
                                { 'H', 'H', 'H' } };
 
    // Function Call
    vector<vector<int> > ans = chefAndWells(n, m, c);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)
            cout << ans[i][j] << " ";
        cout << endl;
    }
    return 0;
}


Java




// Java code for the above approach:
import java.util.*;
 
class GFG {
    static List<List<Integer> >
    chefAndWells(int n, int m, List<List<Character> > c)
    {
        List<List<Integer> > res = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            List<Integer> row = new ArrayList<>(
                Collections.nCopies(m, (int)1e9));
            res.add(row);
        }
 
        Queue<int[]> q = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (c.get(i).get(j) == 'W') {
                    q.offer(new int[] { i, j });
                    res.get(i).set(j, 0);
                }
            }
        }
 
        int[] dx = { 0, 0, -1, 1 };
        int[] dy = { -1, 1, 0, 0 };
        while (!q.isEmpty()) {
            int[] cur = q.poll();
            int curx = cur[0], cury = cur[1];
            for (int i = 0; i < 4; i++) {
                int x = curx + dx[i], y = cury + dy[i];
                if (x >= 0 && x < n && y >= 0 && y < m
                    && c.get(x).get(y) != 'N'
                    && res.get(x).get(y)
                           > res.get(curx).get(cury) + 1) {
                    q.offer(new int[] { x, y });
                    res.get(x).set(
                        y, res.get(curx).get(cury) + 1);
                }
            }
        }
 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (c.get(i).get(j) == '.') {
                    res.get(i).set(j, 0);
                }
                else if (res.get(i).get(j) == (int)1e9
                         && c.get(i).get(j) != 'N') {
                    res.get(i).set(j, -1);
                }
                else if (res.get(i).get(j) == (int)1e9
                         && c.get(i).get(j) != 'H') {
                    res.get(i).set(j, 0);
                }
                else {
                    res.get(i).set(j,
                                   res.get(i).get(j) * 2);
                }
            }
        }
 
        return res;
    }
 
    public static void main(String[] args)
    {
        int n = 3, m = 3;
        List<List<Character> > c = new ArrayList<>();
        c.add(Arrays.asList('H', 'H', 'H'));
        c.add(Arrays.asList('H', 'W', 'H'));
        c.add(Arrays.asList('H', 'H', 'H'));
 
        // Function Call
        List<List<Integer> > ans = chefAndWells(n, m, c);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.print(ans.get(i).get(j) + " ");
            }
            System.out.println();
        }
    }
}
 
// This code is contributed by rambabuguphka


Python3




from collections import deque
 
# Nikunj Sonigara
def chefAndWells(n, m, c):
    res = [[float('inf')] * m for _ in range(n)]
    q = deque()
 
    for i in range(n):
        for j in range(m):
            if c[i][j] == 'W':
                q.append((i, j))
                res[i][j] = 0
 
    dx = [0, 0, -1, 1]
    dy = [-1, 1, 0, 0]
 
    while q:
        curx, cury = q.popleft()
        for i in range(4):
            x = curx + dx[i]
            y = cury + dy[i]
            if 0 <= x < n and 0 <= y < m and c[x][y] != 'N' and res[x][y] > res[curx][cury] + 1:
                q.append((x, y))
                res[x][y] = res[curx][cury] + 1
 
    for i in range(n):
        for j in range(m):
            if c[i][j] == '.':
                res[i][j] = 0
            elif res[i][j] == float('inf') and c[i][j] != 'N':
                res[i][j] = -1
            elif res[i][j] == float('inf') and c[i][j] != 'H':
                res[i][j] = 0
            else:
                res[i][j] *= 2
 
    return res
 
# Driver code
n = 3
m = 3
c = [['H', 'H', 'H'],
     ['H', 'W', 'H'],
     ['H', 'H', 'H']]
 
# Function call
ans = chefAndWells(n, m, c)
for i in range(n):
    for j in range(m):
        print(ans[i][j], end=' ')
    print()


C#




using System;
using System.Collections.Generic;
 
public class Solution
{
    public static List<List<int>> ChefAndWells(int n, int m, List<List<char>> c)
    {
        // Create a 2D list to store the result
        List<List<int>> res = new List<List<int>>();
        for (int i = 0; i < n; i++)
        {
            res.Add(new List<int>());
            for (int j = 0; j < m; j++)
            {
                res[i].Add(int.MaxValue); // Initialize with a large value
            }
        }
 
        // Initialize a queue for BFS
        Queue<Tuple<int, int>> q = new Queue<Tuple<int, int>>();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (c[i][j] == 'W')
                {
                    q.Enqueue(Tuple.Create(i, j)); // Add water sources to the queue
                    res[i][j] = 0; // Set their distance to 0
                }
            }
        }
 
        int[] dx = { 0, 0, -1, 1 };
        int[] dy = { -1, 1, 0, 0 };
 
        // Perform BFS
        while (q.Count > 0)
        {
            var cur = q.Dequeue();
            int curx = cur.Item1, cury = cur.Item2;
 
            for (int i = 0; i < 4; i++)
            {
                int x = curx + dx[i], y = cury + dy[i];
                if (x >= 0 && x < n && y >= 0 && y < m
                    && c[x][y] != 'N'
                    && res[x][y] > res[curx][cury] + 1)
                {
                    q.Enqueue(Tuple.Create(x, y));
                    res[x][y] = res[curx][cury] + 1; // Update distances
                }
            }
        }
 
        // Calculate the final result based on the problem statement
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (c[i][j] == '.')
                    res[i][j] = 0;
                else if (res[i][j] == int.MaxValue && c[i][j] != 'N')
                    res[i][j] = -1;
                else if (res[i][j] == int.MaxValue && c[i][j] != 'H')
                    res[i][j] = 0;
                else
                    res[i][j] *= 2;
            }
        }
 
        return res;
    }
 
    public static void Main(string[] args)
    {
        int n = 3, m = 3;
        List<List<char>> c = new List<List<char>>
        {
            new List<char> { 'H', 'H', 'H' },
            new List<char> { 'H', 'W', 'H' },
            new List<char> { 'H', 'H', 'H' }
        };
 
        List<List<int>> ans = ChefAndWells(n, m, c);
 
        // Print the result
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                Console.Write(ans[i][j] + " ");
            }
            Console.WriteLine();
        }
    }
}


Javascript




function chefAndWells(n, m, c) {
    let res = new Array(n).fill(null).map(() => new Array(m).fill(1e9));
    let q = [];
    const dx = [0, 0, -1, 1];
    const dy = [-1, 1, 0, 0];
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            if (c[i][j] === 'W') {
                q.push([i, j]);
                res[i][j] = 0;
            }
        }
    }
    // BFS traversal
    while (q.length > 0) {
        const cur = q.shift();
        const curx = cur[0];
        const cury = cur[1];
        for (let i = 0; i < 4; i++) {
            const x = curx + dx[i];
            const y = cury + dy[i];
            if (x >= 0 && x < n && y >= 0 && y < m
                && c[x][y] !== 'N'
                && res[x][y] > res[curx][cury] + 1) {
                q.push([x, y]);
                res[x][y] = res[curx][cury] + 1;
            }
        }
    }
    // Post-processing
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            if (c[i][j] === '.')
                res[i][j] = 0;
            else if (res[i][j] === 1e9 && c[i][j] !== 'N')
                res[i][j] = -1;
            else if (res[i][j] === 1e9 && c[i][j] !== 'H')
                res[i][j] = 0;
            else
                res[i][j] *= 2;
        }
    }
    return res;
}
// Driver code
const n = 3;
const m = 3;
const c = [['H', 'H', 'H'],
           ['H', 'W', 'H'],
           ['H', 'H', 'H']];
// Function call
const ans = chefAndWells(n, m, c);
for (let i = 0; i < n; i++) {
    console.log(ans[i].join(' '));
}


Output

4 2 4 
2 0 2 
4 2 4 

Time Complexity: O(n*m + n*m) At first As each cell of the matrix is visited only once during the BFS traversal. Finally, the algorithm iterates over the matrix again to calculate the minimum distance from each house to the well.
Auxiliary Space: O(n*m) + O(n*m) + O(n*m) = O(n*m) The algorithm uses a 2D boolean array of size nm to keep track of visited cells during the BFS traversal. It also uses a queue to store the cells to be visited during the BFS traversal, which can contain up to nm elements in the worst case. Additionally, it uses a 2D integer array of size n*m to store the minimum distance of each house from the well.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads