Open In App

CSES Solutions – Grid Paths (DP)

Last Updated : 27 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Consider an N X N grid whose squares may have traps. It is not allowed to move to a square with a trap. Your task is to calculate the number of paths from the upper-left square to the lower-right square. You can only move right or down.

Note: .‘ denotes an empty cell, and ‘*' denotes a trap.

Grid-Paths

Grid Paths

Examples:

Input: N = 4, grid[][] = {“….”, “.*..”, “…*”, “*…”}
Output: 3
Explanation: There are 3 ways to reach the lower-right square, starting from the upper-left square.

Input: N = 3, grid[][] = {“…”, “…”, “..*”}
Output: 0
Explanation: There is no way to reach the lower-right square, starting from the upper-left square.

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

The problem can be solved using Dynamic Programming. Maintain a dp[][] table such that dp[r] = number of ways to reach row r, column c from cell(0, 0).

We say there is one way to reach (0,0), dp[0][0] = 1.

When navigating the grid where each cell contains either a ‘.' or a ‘#', we can move either right or down. The number of ways to reach a particular cell is the sum of the ways to reach the cell above it and the ways to reach the cell to its left. Additionally, any cell containing a ‘#' is inaccessible (with zero ways to reach it). So, for each each cell (i, j), dp[i][j] = dp[i – 1][j] + dp[i][j – 1].

Step-by-step algorithm:

  • Maintain a dp[][] array such that dp[i][j] stores the number of ways to reach cell(i, j) from cell(0, 0).
  • Initialize all the cells of dp[][] array with 0.
  • Fill the first row with 1s starting from (0, 0) till we encounter a blocked cell.
  • Fill the first column with 1s starting from (0, 0) till we encounter a blocked cell.
  • For all the other cells (i, j):
    • If the cell is blocked, dp[i][j] = 0.
    • If the cell is empty, dp[i][j] = dp[i – 1][j] + dp[i][j – 1].
  • After all the iterations, return dp[N-1][N-1] as the final answer.

Below is the implementation of the algorithm:

C++
#include <bits/stdc++.h>
#define ll long long int
#define mod 1000000007
using namespace std;

ll solve(vector<string>& grid, ll N)
{
    // dp[][] array such that dp[i][j] stores the number of
    // ways to reach cell(i, j) from cell(0, 0)
    vector<vector<ll> > dp(N, vector<ll>(N, 0));


    // Finding the number of ways for the first column
    for (int i = 0; i < N; i++) {
        if (grid[i][0] == '*')
            break;
        dp[i][0] = 1;
    }

    // Finding the number of ways for the first row
    for (int j = 0; j < N; j++) {
        if (grid[0][j] == '*')
            break;
        dp[0][j] = 1;
    }

    // Finding the number of ways for the remaining grid
    for (int i = 1; i < N; i++) {
        for (int j = 1; j < N; j++) {
            // If the cell is blocked, then move to the next
            // cell
            if (grid[i][j] == '*')
                continue;

            // The number of ways to reach cell(i, j) =
            // number of ways to reach cell (i-1,j) + number
            // of ways to reach cell(i,j-1)
            dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % mod;
        }
    }
    
      // Return the number of ways to reach the last cell of the grid
    return dp[N - 1][N -1];
}

int main()
{
      // Sample Input
    ll N = 4;
    vector<string> grid = {"....", ".*..", "...*", "*..."};
  
    cout << solve(grid, N) << "\n";
}
Java
import java.util.*;

public class Main {
    // Function to find the number of ways to the reach the bottom-right cell
    static long GFG(ArrayList<String> grid, int N, int mod) {
        long[][] dp = new long[N][N];
        // Finding the number of ways for first column
        for (int i = 0; i < N; i++) {
            if (grid.get(i).charAt(0) == '*')
                break;
            dp[i][0] = 1;
        }
        // Finding the number of ways for the first row
        for (int j = 0; j < N; j++) {
            if (grid.get(0).charAt(j) == '*')
                break;
            dp[0][j] = 1;
        }
        // Finding the number of ways for remaining grid
        for (int i = 1; i < N; i++) {
            for (int j = 1; j < N; j++) {
                // If the cell is blocked, then move to the next cell
                if (grid.get(i).charAt(j) == '*')
                    continue;
                dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % mod;
            }
        }       
        return dp[N - 1][N - 1];
    }
    public static void main(String[] args) {
        // Input
        int N = 4;
        ArrayList<String> grid = new ArrayList<>(Arrays.asList("....", ".*..", "...*", "*..."));
        int mod = 1000000007;
        System.out.println(GFG(grid, N, mod));
    }
}
C#
using System;
using System.Collections.Generic;

public class Geeks
{
    // Function to find the number of ways to reach the bottom-right cell
    static long GFG(List<string> grid, int N, int mod)
    {
        long[,] dp = new long[N, N];
        // Finding the number of ways for first column
        for (int i = 0; i < N; i++)
        {
            if (grid[i][0] == '*')
                break;
            dp[i, 0] = 1;
        }
        // Finding the number of ways for the first row
        for (int j = 0; j < N; j++)
        {
            if (grid[0][j] == '*')
                break;
            dp[0, j] = 1;
        }
        // Finding the number of ways for remaining grid
        for (int i = 1; i < N; i++)
        {
            for (int j = 1; j < N; j++)
            {
                // If the cell is blocked, then move to the next cell
                if (grid[i][j] == '*')
                    continue;
                dp[i, j] = (dp[i - 1, j] + dp[i, j - 1]) % mod;
            }
        }
        return dp[N - 1, N - 1];
    }
    public static void Main(string[] args)
    {
        // Input
        int N = 4;
        List<string> grid = new List<string> { "....", ".*..", "...*", "*..." };
        int mod = 1000000007;
        Console.WriteLine(GFG(grid, N, mod));
    }
}
JavaScript
function GFG(grid, N) {
    const mod = 1000000007;
    // Initialize dp array to store the number of the ways to reach each cell
    const dp = Array.from({ length: N }, () => Array(N).fill(0));
    for (let i = 0; i < N; i++) {
        if (grid[i][0] === '*') break;
        dp[i][0] = 1;
    }
    // Finding the number of ways for the first row
    for (let j = 0; j < N; j++) {
        if (grid[0][j] === '*') break;
        dp[0][j] = 1;
    }
    // Finding the number of ways for remaining grid
    for (let i = 1; i < N; i++) {
        for (let j = 1; j < N; j++) {
            // If the cell is blocked, then move to the next cell
            if (grid[i][j] === '*') continue;
            dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % mod;
        }
    }
    return dp[N - 1][N - 1];
}
// Sample Input
const N = 4;
const grid = ["....", ".*..", "...*", "*..."];
console.log(GFG(grid, N));
Python3
def GFG(grid, N):
    mod = 1000000007
    # Initialize dp array to store the number of the ways to reach each cell
    dp = [[0]*N for _ in range(N)]
    for i in range(N):
        if grid[i][0] == '*':
            break
        dp[i][0] = 1
    # Finding the number of ways for the first row
    for j in range(N):
        if grid[0][j] == '*':
            break
        dp[0][j] = 1
    # Finding the number of ways for remaining grid
    for i in range(1, N):
        for j in range(1, N):
            # If the cell is blocked, then move to the next cell
            if grid[i][j] == '*':
                continue
            dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % mod
    return dp[N - 1][N - 1]

# Sample Input
N = 4
grid = ["....", ".*..", "...*", "*..."]
print(GFG(grid, N))

Output
3

Time Complexity: O(N * N), where N is the number of rows or columns in the grid.
Auxiliary Space: O(N * N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads