DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
Assignment-4
Student Name: Mandeep Singh UID:23BCS12641
Problem:1
Aim: To calculate the number of unique paths a robot can take to move from the top-left to the
bottom-right corner of an m x n grid, moving only right or down.
Objective:
To compute the number of unique paths a robot can take from the top-left to the bottom-right
corner of an m x n grid, moving only right or down at each step.
Algorithm:
1. Create a 2D array dp[m][n] to store the number of unique paths to each cell.
2. Initialize the first row and the first column to 1 because there's only one way to reach any
cell in the first row (all right moves) or first column (all down moves).
3. Use the recurrence relation:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
the number of ways to reach cell (i,j) is the sum of ways to reach from the top (i-1,j)
and left (i,j-1).
4. The bottom-right corner will contain the final answer.
Code:
#include <iostream>
using namespace std;
int uniquePaths(int m, int n) {
int dp[100][100];
for (int i = 0; i < m; i++)
dp[i][0] = 1;
for (int j = 0; j < n; j++)
dp[0][j] = 1;
DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
int main() {
int m = 3, n = 3;
cout << "Number of unique paths in a " << m << "x" << n << " grid: " << uniquePaths(m, n)
<< endl;
return 0;
Output:
Learning Outcomes:
Understand how to use Dynamic Programming to solve combinatorial grid-based
problems.
Learn how to construct and initialize a 2D vector (array) in C++.
Understand grid traversal logic using nested loops.
Improve your problem-solving skills by applying recurrence relations.
DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
Problem:2
Aim: To find all possible paths for a rat to travel from the top-left corner to the bottom- right
corner of an n x n matrix, avoiding blocked cells and not revisiting any cell in the same path.
Objective:
To print all valid paths for a rat from (0,0) to (n-1,n-1) in an n x n grid, using backtracking, avoiding blocked
cells, and not revisiting any cell.
Algorithm:
1. Use a 2D array maze[n][n] for the grid.
2. Use a 2D visited[n][n] array to keep track of visited cells in the current path.
3. Move in the four directions — Down (D), Left (L), Right (R), and Up (U) — recursively.
4. If destination (n-1,n-1) is reached, print the path.
5. Use backtracking to unmark the current cell before returning.
Code:
#include <iostream>
#include <string>
using namespace std;
const int MAX = 10;
int maze[MAX][MAX];
bool visited[MAX][MAX];
int n;
int dx[] = {1, 0, 0, -1};
int dy[] = {0, -1, 1, 0};
char dir[] = {'D', 'L', 'R', 'U'};
bool isSafe(int x, int y) {
return (x >= 0 && x < n && y >= 0 && y < n && maze[x][y] == 1 && !visited[x][y]);
}
void findPaths(int x, int y, string path) {
if (x == n - 1 && y == n - 1) {
cout << path << endl;
return;
}
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
if (isSafe(newX, newY)) {
visited[newX][newY] = true;
findPaths(newX, newY, path + dir[i]);
visited[newX][newY] = false; // Backtrack
}
}
}
int main() {
n = 4;
int inputMaze[MAX][MAX] = {
{1, 0, 0, 0},
{1, 1, 0, 1},
{0, 1, 0, 0},
{1, 1, 1, 1}
};
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
maze[i][j] = inputMaze[i][j];
visited[i][j] = false;
}
}
if (maze[0][0] == 1) {
visited[0][0] = true;
cout << "Possible paths:" << endl;
findPaths(0, 0, "");
} else {
cout << "Start position is blocked." << endl;
}
return 0;
}
Output:
DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
Learning outcomes:
Learn how to implement backtracking without STL.
Understand grid-based traversal using 2D arrays.
Learn how to manage recursive functions using basic arrays and strings.
Reinforce understanding of bounds checking and path tracking.
Problem:3
Aim: To determine the maximum profit achievable by scheduling non-overlapping jobs,
each with a start time, end time, and associated profit.
Objective: To compute the maximum profit that can be earned by scheduling a set of non-
overlapping jobs, where each job has a start time, end time, and a profit, by selecting the
optimal subset of jobs such that no two selected jobs overlap.
Code:
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 100;
struct Job {
int start, end, profit;
};
bool compare(Job a, Job b) {
return a.end < b.end;
}
int latestNonConflict(Job jobs[], int index) {
int low = 0, high = index - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (jobs[mid].end <= jobs[index].start) {
if (jobs[mid + 1].end <= jobs[index].start)
low = mid + 1;
else
return mid;
} else {
high = mid - 1;
}
}
DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
return -1;
}
int findMaxProfit(Job jobs[], int n) {
sort(jobs, jobs + n, compare);
int dp[MAX];
dp[0] = jobs[0].profit;
for (int i = 1; i < n; i++) {
int inclProfit = jobs[i].profit;
int l = latestNonConflict(jobs, i);
if (l != -1)
inclProfit += dp[l];
dp[i] = max(dp[i - 1], inclProfit);
}
return dp[n - 1];
}
int main() {
Job jobs[] = {
{1, 3, 50},
{3, 5, 20},
{6, 19, 100},
{2, 100, 200}
};
int n = 4;
int maxProfit = findMaxProfit(jobs, n);
cout << "Maximum Profit: " << maxProfit << endl;
return 0;
}
Output:
Learning Outcomes:
Understand dynamic programming for interval scheduling.
Learn how to replace vectors with arrays in real problems.
Master sorting and binary search manually in structured data.
Reinforce concepts of non-overlapping job selection.
DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
Problem:4
Aim: To develop a program that solves a given Sudoku puzzle by filling empty cells
such that all Sudoku rules are satisfied.
Objective:
Implement a Sudoku solver that can fill a 9x9 Sudoku grid.
Ensure that the solution follows Sudoku rules:
Each row must contain digits 1–9 with no repetition.
Each column must contain digits 1–9 with no repetition.
Each of the nine 3×3 subgrids must contain digits 1–9 with no repetition.
Use recursion and backtracking for solving.
Code:
#include <iostream>
using namespace std;
#define N 9
void printGrid(int grid[N][N]) {
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++)
cout << grid[row][col] << " ";
cout << endl;
}
}
bool isSafe(int grid[N][N], int row, int col, int num) {
for (int x = 0; x < N; x++) {
if (grid[row][x] == num || grid[x][col] == num)
return false;
}
int startRow = row - row % 3, startCol = col - col % 3;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (grid[i + startRow][j + startCol] == num)
return false;
return true;
}
bool solveSudoku(int grid[N][N]) {
int row, col;
bool emptyFound = false;
DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
for (row = 0; row < N; row++) {
for (col = 0; col < N; col++) {
if (grid[row][col] == 0) {
emptyFound = true;
break;
}
}
if (emptyFound) break;
}
if (!emptyFound) return true;
for (int num = 1; num <= 9; num++) {
if (isSafe(grid, row, col, num)) {
grid[row][col] = num;
if (solveSudoku(grid))
return true;
grid[row][col] = 0; // Backtrack
}
}
return false;
}
int main() {
int grid[N][N] = {
{5, 3, 0, 0, 7, 0, 0, 0, 0},
{6, 0, 0, 1, 9, 5, 0, 0, 0},
{0, 9, 8, 0, 0, 0, 0, 6, 0},
{8, 0, 0, 0, 6, 0, 0, 0, 3},
{4, 0, 0, 8, 0, 3, 0, 0, 1},
{7, 0, 0, 0, 2, 0, 0, 0, 6},
{0, 6, 0, 0, 0, 0, 2, 8, 0},
{0, 0, 0, 4, 1, 9, 0, 0, 5},
{0, 0, 0, 0, 8, 0, 0, 7, 9}
};
if (solveSudoku(grid) == true)
printGrid(grid);
else
cout << "No solution exists";
return 0;
}
DEPARTMENT OF
COMPUTERSCIENCE & ENGINEERING
Output:
Learning Outcome:
How to implement backtracking algorithms in C++.
How to apply constraints and recursion in solving logic-based problems.
Enhanced understanding of 2D arrays and nested loops.
Debugging and validating complex logical constraints.