# Minimum cost to reach the last cell of a grid with directions

Last Updated : 05 Mar, 2024

Given a 2D matrix grid[][] of size M X N, where each cell of the grid has a character denoting the next cell we should visit we are at the current cell. The character at any cell can be:

• R‘ which means go to the cell to the right. (i.e from grid[i][j] to grid[i][j + 1])
• L‘ which means go to the cell to the left. (i.e go from grid[i][j] to grid[i][j – 1])
• D‘ which means go to the lower cell. (i.e go from grid[i][j] to grid[i + 1][j])
• U‘ which means go to the upper cell. (i.e go from grid[i][j] to grid[i – 1][j])

At any cell (i, j) we can either move in the direction denoted by character grid[i][j] with a cost of 0 or we can move in some other direction with a cost of 1. Starting from the cell (0, 0), the task is to reach cell (M-1, N-1) with minimum cost. The path does not have to be the shortest.

Note: The character may point to the outside of the grid as well.

Examples:

Input: N = 4, M = 4, grid[][]= {{‘R’, ‘R’, ‘R’, ‘R’}, {‘L’, ‘L’, ‘L’, ‘L’}, {‘R’, ‘R’, ‘R’, ‘R’}, {‘L’, ‘L’, ‘L’, ‘L’}}
Output: 3
Explanation: The path from (0, 0) to (3, 3) is:

• (0, 0) -> (0, 1) -> (0, 2) -> (0, 3), cost = 0
• (0, 3) -> (1, 3), cost = 1
• (1, 3) -> (1, 2) -> (1, 1) -> (1, 0), cost = 0
• (1, 0) -> (2, 0), cost = 1
• (2, 0) -> (2, 1) –> (2, 2) –> (2, 3), cost = 0
• (2, 3) -> (3, 3), cost = 1

The total cost = 0 + 1 + 0 + 1 + 0 + 1 = 3.

Input: N = 3, M = 3, grid = {{‘R’, ‘R’, ‘D’}, {‘D’, ‘L’, ‘L’}, {‘R’, ‘R’, ‘U’}}
Output: 0
Explanation: The path from (0, 0) to (2, 2) is:

• (0, 0) -> (0, 1) -> (0, 2) -> (1, 2) -> (1, 1) -> (1, 0) -> (2, 0) -> (2, 1) -> (2, 2), cost = 0

The total cost = 0.

Approach: To solve the problem, follow the below idea:

The problem can be solved using 0-1 BFS by considering the grid as a graph where edge weights are limited to 0 and 1 only. If we move in the same direction as denoted by the current cell, then the edge cost will be 0 otherwise if we move in any other direction, then the edge cost will be 1. Now, we can run a 0-1 BFS using a deque to find the minimum cost from cell (0, 0) to cell (M – 1, N – 1).

Step-by-step algorithm:

• Maintain a deque of pairs, say dq to store the row and column of the cells.
• Also maintain a cost[][] array, such that cost[i][j] stores the minimum cost to reach cell (i, j) starting from (0, 0).
• Push the cell (0, 0) to the dq.
• Iterate till dq is not empty:
• Pop the front element (r, c).
• For all the neighboring cells, push the cell to the front of dq if the neighboring cell is in the same direction as denoted by grid[r], otherwise push the cell to the back of dq.
• Also, the cell will only be pushed if the cell has not been visited yet.
• We can keep track of the visited cells using the cost[][] array.
• Finally, return the value stored at cost[M – 1][N – 1].

Below is the implementation of the algorithm:

## C++

 `#include ` `#include ` `#include ` `using` `namespace` `std;`   `// Method to check whether a cell is in the grid or not` `bool` `isValid(``int` `r, ``int` `c, ``int` `M, ``int` `N)` `{` `    ``return` `r >= 0 && c >= 0 && r < M && c < N;` `}`   `// Method to find the minimum cost to reach cell (M-1, N-1)` `int` `minCost(vector>& grid)` `{` `    ``// 0-1 BFS` `    ``deque> dq;` `    ``int` `M = grid.size(), N = grid[0].size();`   `    ``// vector to store the minimum cost to reach a` `    ``// particular cell` `    ``vector> cost(M, vector<``int``>(N, 1e9));` `    ``cost[0][0] = 0;` `    ``dq.push_back({0, 0});` `    ``int` `dr[] = {0, 0, -1, 1};` `    ``int` `dc[] = {1, -1, 0, 0};`   `    ``while` `(!dq.empty())` `    ``{` `        ``int` `r = dq.front().first;` `        ``int` `c = dq.front().second;` `        ``dq.pop_front();` `        ``for` `(``int` `i = 0; i < 4; i++)` `        ``{` `            ``int` `new_r = r + dr[i];` `            ``int` `new_c = c + dc[i];` `            ``if` `(isValid(new_r, new_c, M, N))` `            ``{` `                ``int` `new_d = cost[r];` `                ``bool` `directionChange = ``false``;` `                ``// If the next cell is in a different` `                ``// direction` `                ``if` `((grid[r] != ``'R'` `&& dr[i] == 0 &&` `                     ``dc[i] == 1) ||` `                    ``(grid[r] != ``'L'` `&& dr[i] == 0 &&` `                     ``dc[i] == -1) ||` `                    ``(grid[r] != ``'D'` `&& dr[i] == 1 &&` `                     ``dc[i] == 0) ||` `                    ``(grid[r] != ``'U'` `&& dr[i] == -1 &&` `                     ``dc[i] == 0))` `                ``{` `                    ``new_d += 1;` `                    ``directionChange = ``true``;` `                ``}`   `                ``// If the cell is unvisited` `                ``if` `(cost[new_r][new_c] > new_d)` `                ``{` `                    ``cost[new_r][new_c] = new_d;`   `                    ``// If the next cell is in the same` `                    ``// direction as written in grid[r]` `                    ``if` `(directionChange)` `                    ``{` `                        ``dq.push_back({new_r, new_c});` `                    ``}` `                    ``// If the next cell is in a different` `                    ``// direction as written in grid[r]` `                    ``else` `                    ``{` `                        ``dq.push_front({new_r, new_c});` `                    ``}` `                ``}` `            ``}` `        ``}` `    ``}` `    ``return` `cost[M - 1][N - 1];` `}`   `int` `main()` `{` `    ``vector> grid = {{``'R'``, ``'R'``, ``'R'``, ``'R'``},` `                                  ``{``'L'``, ``'L'``, ``'L'``, ``'L'``},` `                                  ``{``'R'``, ``'R'``, ``'R'``, ``'R'``},` `                                  ``{``'L'``, ``'L'``, ``'L'``, ``'L'``}};` `    ``cout << minCost(grid) << ``"\n"``;` `    ``return` `0;` `}`

## Java

 `import` `java.util.ArrayDeque;` `import` `java.util.Deque;`   `public` `class` `Main {`   `    ``// Method to check whether a cell is in the grid or not` `    ``static` `boolean` `isValid(``int` `r, ``int` `c, ``int` `M, ``int` `N) {` `        ``return` `r >= ``0` `&& c >= ``0` `&& r < M && c < N;` `    ``}`   `    ``// Method to find the minimum cost to reach cell (M-1, N-1)` `    ``static` `int` `minCost(``char``[][] grid) {` `        ``// 0-1 BFS` `        ``Deque<``int``[]> dq = ``new` `ArrayDeque<>();` `        ``int` `M = grid.length, N = grid[``0``].length;`   `        ``// Array to store the minimum cost to reach a` `        ``// particular cell` `        ``int``[][] cost = ``new` `int``[M][N];` `        ``for` `(``int` `i = ``0``; i < M; i++) {` `            ``for` `(``int` `j = ``0``; j < N; j++) {` `                ``cost[i][j] = Integer.MAX_VALUE;` `            ``}` `        ``}`   `        ``cost[``0``][``0``] = ``0``;` `        ``dq.addLast(``new` `int``[]{``0``, ``0``});` `        ``int``[] dr = {``0``, ``0``, -``1``, ``1``};` `        ``int``[] dc = {``1``, -``1``, ``0``, ``0``};`   `        ``while` `(!dq.isEmpty()) {` `            ``int``[] current = dq.pollFirst();` `            ``int` `r = current[``0``];` `            ``int` `c = current[``1``];`   `            ``for` `(``int` `i = ``0``; i < ``4``; i++) {` `                ``int` `new_r = r + dr[i];` `                ``int` `new_c = c + dc[i];` `                ``if` `(isValid(new_r, new_c, M, N)) {` `                    ``int` `new_d = cost[r];` `                    ``boolean` `directionChange = ``false``;`   `                    ``// If the next cell is in a different direction` `                    ``if` `((grid[r] != ``'R'` `&& dr[i] == ``0` `&& dc[i] == ``1``)` `                            ``|| (grid[r] != ``'L'` `&& dr[i] == ``0` `&& dc[i] == -``1``)` `                            ``|| (grid[r] != ``'D'` `&& dr[i] == ``1` `&& dc[i] == ``0``)` `                            ``|| (grid[r] != ``'U'` `&& dr[i] == -``1` `&& dc[i] == ``0``)) {` `                        ``new_d += ``1``;` `                        ``directionChange = ``true``;` `                    ``}`   `                    ``// If the cell is unvisited` `                    ``if` `(cost[new_r][new_c] > new_d) {` `                        ``cost[new_r][new_c] = new_d;`   `                        ``// If the next cell is in the same direction` `                        ``// as written in grid[r]` `                        ``if` `(directionChange) {` `                            ``dq.addLast(``new` `int``[]{new_r, new_c});` `                        ``}` `                        ``// If the next cell is in a different` `                        ``// direction as written in grid[r]` `                        ``else` `{` `                            ``dq.addFirst(``new` `int``[]{new_r, new_c});` `                        ``}` `                    ``}` `                ``}` `            ``}` `        ``}` `        ``return` `cost[M - ``1``][N - ``1``];` `    ``}`   `    ``public` `static` `void` `main(String[] args) {` `        ``char``[][] grid = {` `                ``{``'R'``, ``'R'``, ``'R'``, ``'R'``},` `                ``{``'L'``, ``'L'``, ``'L'``, ``'L'``},` `                ``{``'R'``, ``'R'``, ``'R'``, ``'R'``},` `                ``{``'L'``, ``'L'``, ``'L'``, ``'L'``}` `        ``};` `        ``System.out.println(minCost(grid));` `    ``}` `}`   `// This code is contributed by rambabuguphka`

## C#

 `using` `System;` `using` `System.Collections.Generic;`   `class` `Program` `{` `    ``// Method to check whether a cell is in the grid or not` `    ``static` `bool` `IsValid(``int` `r, ``int` `c, ``int` `M, ``int` `N)` `    ``{` `        ``return` `r >= 0 && c >= 0 && r < M && c < N;` `    ``}`   `    ``// Method to find the minimum cost to reach cell (M-1, N-1)` `    ``static` `int` `MinCost(``char``[][] grid)` `    ``{` `        ``// 0-1 BFS` `        ``var` `dq = ``new` `Queue>();` `        ``int` `M = grid.Length, N = grid[0].Length;`   `        ``// vector to store the minimum cost to reach a` `        ``// particular cell` `        ``var` `cost = ``new` `int``[M][];` `        ``for` `(``int` `i = 0; i < M; i++)` `        ``{` `            ``cost[i] = ``new` `int``[N];` `            ``for` `(``int` `j = 0; j < N; j++)` `            ``{` `                ``cost[i][j] = ``int``.MaxValue;` `            ``}` `        ``}` `        ``cost[0][0] = 0;` `        ``dq.Enqueue(``new` `Tuple<``int``, ``int``>(0, 0));` `        ``int``[] dr = { 0, 0, -1, 1 };` `        ``int``[] dc = { 1, -1, 0, 0 };`   `        ``while` `(dq.Count > 0)` `        ``{` `            ``var` `front = dq.Dequeue();` `            ``int` `r = front.Item1;` `            ``int` `c = front.Item2;` `            ``for` `(``int` `i = 0; i < 4; i++)` `            ``{` `                ``int` `new_r = r + dr[i];` `                ``int` `new_c = c + dc[i];` `                ``if` `(IsValid(new_r, new_c, M, N))` `                ``{` `                    ``int` `new_d = cost[r];` `                    ``bool` `directionChange = ``false``;` `                    ``// If the next cell is in a different` `                    ``// direction` `                    ``if` `((grid[r] != ``'R'` `&& dr[i] == 0 &&` `                         ``dc[i] == 1) ||` `                        ``(grid[r] != ``'L'` `&& dr[i] == 0 &&` `                         ``dc[i] == -1) ||` `                        ``(grid[r] != ``'D'` `&& dr[i] == 1 &&` `                         ``dc[i] == 0) ||` `                        ``(grid[r] != ``'U'` `&& dr[i] == -1 &&` `                         ``dc[i] == 0))` `                    ``{` `                        ``new_d += 1;` `                        ``directionChange = ``true``;` `                    ``}`   `                    ``// If the cell is unvisited` `                    ``if` `(cost[new_r][new_c] > new_d)` `                    ``{` `                        ``cost[new_r][new_c] = new_d;`   `                        ``// If the next cell is in the same` `                        ``// direction as written in grid[r]` `                        ``if` `(directionChange)` `                        ``{` `                            ``dq.Enqueue(``new` `Tuple<``int``, ``int``>(new_r, new_c));` `                        ``}` `                        ``// If the next cell is in a different` `                        ``// direction as written in grid[r]` `                        ``else` `                        ``{` `                            ``dq.Enqueue(``new` `Tuple<``int``, ``int``>(new_r, new_c));` `                        ``}` `                    ``}` `                ``}` `            ``}` `        ``}` `        ``return` `cost[M - 1][N - 1];` `    ``}`   `    ``static` `void` `Main()` `    ``{` `        ``char``[][] grid = {` `            ``new` `char``[] {``'R'``, ``'R'``, ``'R'``, ``'R'``},` `            ``new` `char``[] {``'L'``, ``'L'``, ``'L'``, ``'L'``},` `            ``new` `char``[] {``'R'``, ``'R'``, ``'R'``, ``'R'``},` `            ``new` `char``[] {``'L'``, ``'L'``, ``'L'``, ``'L'``}` `        ``};` `        ``Console.WriteLine(MinCost(grid));` `    ``}` `}`

## Javascript

 `// Method to check whether a cell is in the grid or not` `function` `isValid(r, c, M, N) {` `    ``return` `r >= 0 && c >= 0 && r < M && c < N;` `}`   `// Method to find the minimum cost to reach cell (M-1, N-1)` `function` `minCost(grid) {` `    ``// 0-1 BFS` `    ``const dq = [];` `    ``const M = grid.length;` `    ``const N = grid[0].length;`   `    ``// matrix to store the minimum cost to reach a particular cell` `    ``const cost = Array.from({ length: M }, () => Array(N).fill(1e9));` `    ``cost[0][0] = 0;` `    ``dq.push([0, 0]);` `    ``const dr = [0, 0, -1, 1];` `    ``const dc = [1, -1, 0, 0];`   `    ``while` `(dq.length > 0) {` `        ``const [r, c] = dq.shift();`   `        ``for` `(let i = 0; i < 4; i++) {` `            ``const new_r = r + dr[i];` `            ``const new_c = c + dc[i];`   `            ``if` `(isValid(new_r, new_c, M, N)) {` `                ``let new_d = cost[r];` `                ``let directionChange = ``false``;`   `                ``// If the next cell is in a different direction` `                ``if` `(` `                    ``(grid[r] !== ``'R'` `&& dr[i] === 0 && dc[i] === 1) ||` `                    ``(grid[r] !== ``'L'` `&& dr[i] === 0 && dc[i] === -1) ||` `                    ``(grid[r] !== ``'D'` `&& dr[i] === 1 && dc[i] === 0) ||` `                    ``(grid[r] !== ``'U'` `&& dr[i] === -1 && dc[i] === 0)` `                ``) {` `                    ``new_d += 1;` `                    ``directionChange = ``true``;` `                ``}`   `                ``// If the cell is unvisited` `                ``if` `(cost[new_r][new_c] > new_d) {` `                    ``cost[new_r][new_c] = new_d;`   `                    ``// If the next cell is in the same direction` `                    ``if` `(directionChange) {` `                        ``dq.push([new_r, new_c]);` `                    ``} ``else` `{` `                        ``dq.unshift([new_r, new_c]);` `                    ``}` `                ``}` `            ``}` `        ``}` `    ``}` `    ``return` `cost[M - 1][N - 1];` `}`   `// Example usage` `const grid = [` `    ``[``'R'``, ``'R'``, ``'R'``, ``'R'``],` `    ``[``'L'``, ``'L'``, ``'L'``, ``'L'``],` `    ``[``'R'``, ``'R'``, ``'R'``, ``'R'``],` `    ``[``'L'``, ``'L'``, ``'L'``, ``'L'``]` `];`   `console.log(minCost(grid));`

## Python3

 `from` `collections ``import` `deque`   `# Method to check whether a cell is in the grid or not` `def` `is_valid(r, c, M, N):` `    ``return` `0` `<``=` `r < M ``and` `0` `<``=` `c < N`   `# Method to find the minimum cost to reach cell (M-1, N-1)` `def` `min_cost(grid):` `    ``# 0-1 BFS` `    ``dq ``=` `deque()` `    ``M, N ``=` `len``(grid), ``len``(grid[``0``])`   `    ``# list to store the minimum cost to reach a particular cell` `    ``cost ``=` `[[``1e9``] ``*` `N ``for` `_ ``in` `range``(M)]` `    ``cost[``0``][``0``] ``=` `0` `    ``dq.append((``0``, ``0``))` `    ``dr ``=` `[``0``, ``0``, ``-``1``, ``1``]` `    ``dc ``=` `[``1``, ``-``1``, ``0``, ``0``]`   `    ``while` `dq:` `        ``r, c ``=` `dq.popleft()` `        ``for` `i ``in` `range``(``4``):` `            ``new_r ``=` `r ``+` `dr[i]` `            ``new_c ``=` `c ``+` `dc[i]` `            ``if` `is_valid(new_r, new_c, M, N):` `                ``new_d ``=` `cost[r]` `                ``direction_change ``=` `False` `                ``# If the next cell is in a different direction` `                ``if` `((grid[r] !``=` `'R'` `and` `dr[i] ``=``=` `0` `and` `dc[i] ``=``=` `1``) ``or` `                    ``(grid[r] !``=` `'L'` `and` `dr[i] ``=``=` `0` `and` `dc[i] ``=``=` `-``1``) ``or` `                    ``(grid[r] !``=` `'D'` `and` `dr[i] ``=``=` `1` `and` `dc[i] ``=``=` `0``) ``or` `                    ``(grid[r] !``=` `'U'` `and` `dr[i] ``=``=` `-``1` `and` `dc[i] ``=``=` `0``)):` `                    ``new_d ``+``=` `1` `                    ``direction_change ``=` `True`   `                ``# If the cell is unvisited` `                ``if` `cost[new_r][new_c] > new_d:` `                    ``cost[new_r][new_c] ``=` `new_d`   `                    ``# If the next cell is in the same direction as written in grid[r]` `                    ``if` `direction_change:` `                        ``dq.append((new_r, new_c))` `                    ``# If the next cell is in a different direction as written in grid[r]` `                    ``else``:` `                        ``dq.appendleft((new_r, new_c))` `    ``return` `cost[M ``-` `1``][N ``-` `1``]`   `# Test the function` `grid ``=` `[[``'R'``, ``'R'``, ``'R'``, ``'R'``],` `        ``[``'L'``, ``'L'``, ``'L'``, ``'L'``],` `        ``[``'R'``, ``'R'``, ``'R'``, ``'R'``],` `        ``[``'L'``, ``'L'``, ``'L'``, ``'L'``]]` `print``(min_cost(grid))`

Output

```3

```

Time Complexity: O(M * N), where M is the number of rows and N is the number of columns in the input matrix grid[][]
Auxiliary Space: O(M * N)

Previous
Next