Practical 7-17
Practical 7-17
- 07
Problem Statement: Implement Stassen’s matrix multiplication.
Description:
Strassen's Matrix Multiplication is a divide and conquer approach to solve the
matrix multiplication problems. In the ordinary matrix multiplication, it used to
take O(n3) T.C. Strassen’s method was introduced to reduce the time complexity
from O(n3) to O(n2.81), which is a significant time reduction.
Algorithm :
FUNCTION StrassenMatrixMultiply(A, B)
IF size(A) == 1 THEN
RETURN A[0][0] * B[0][0] // Base case: single element multiplication
// Divide matrices into
submatrices n = size(A)
/2
// Compute M1 to M7
M1 = StrassenMatrixMultiply(A11 + A22, B11 + B22)
M2 = StrassenMatrixMultiply(A21 + A22, B11)
M3 = StrassenMatrixMultiply(A11, B12 - B22)
M4 = StrassenMatrixMultiply(A22, B21 - B11)
M5 = StrassenMatrixMultiply(A11 + A12, B22)
M6 = StrassenMatrixMultiply(A21 - A11, B11 + B12)
M7 = StrassenMatrixMultiply(A12 - A22, B21 + B22
Program:
#include <stdio.h> void main() { printf("Name- Shalini Vashishtha \nRoll
no.-2200970100152\nProgram no – 07 \n");
matrix
// Temporary variables for calculations int s[11];
a[1][0]; // s8
printf("Resultant Matrix:\n");
for (int i = 0; i < 2; i++) {
printf("\n");
}
Output :
Program No. - 08
Problem Statement: Implement Fractional knapsack (Greedy knapsack)
Description:
The greedy approach of the knapsack problem is to calculate the ratio of
profit/weight for each item and sort the item based on this ratio. Then take the
item with the highest ratio and add them as much as we can (can be the whole
element or a fraction of it). This will always give the maximum profit because in
each step, it adds an element such that this is the maximum possible profit for
that much weight. Time Complexity=O(nlogn) dominated by the sorting process.
Algorithm :
Greedy Knapsack(m,n)
//p(1,n) and w(1,n) contain profit & weight respectively of object ordered so that p[i]/w[i]
> p[i+1]/w[i+1]
//m is knapsack size an x(1,n) is solution vector
Program:
#include <stdio.h> int main() {
int n, i, j;
float weight[3] = {18, 15, 10};
float profit[3] = {25, 24, 15}; n=
sizeof(weight)/sizeof(weight[0]);
capacity = 20;
temp= ratio[j];
ratio[j] =ratio[i];
ratio[i] =temp;
// Swap weights
temp =weight[j];
weight[j]= weight[i];
weight[i] = temp;
// Swap profitstemp =
profit[j];
profit[j] = profit[i];
profit[i] = temp;
}
printf("Knapsack problem solution using Greedy approach:\n");
}
}
if (i < n)
Totalvalue += (ratio[i] * capacity); printf("\nThe
maximum value(profit) is : %f\n", Totalvalue);
return 0;
Output :
Program No. - 09
Problem Statement: Implement 0/1 knapsack problem(Dynamic Programming)
Description:
The 0/1 Knapsack Problem is a classic optimization problem where you need to
determine the maximum value that can be carried in a knapsack of a given
capacity, where each item can either be included in the knapsack or excluded
(hence the term 0/1). This problem can be efficiently solved using dynamic
programming.
Algorithm :
FUNCTION Knapsack(weights, values, capacity, n)
DECLARE dp[n+1][capacity+1]
max value is 0
END FOR
END FOR
FOR i FROM 1 TO n
dp[i][j] = dp[i-1][j]
END IF
END FOR
END FOR
RETURN dp[n][capacity] // The maximum value for n items and given capacity
Program:
#include <stdio.h>
// Function to solve the 0/1 Knapsack problem
} else {
}
}
}
return dp[n][capacity]; // The maximum value for n items and given capacity
int maxValue = knapsack(weights, values, capacity, n); // Call the knapsack function
printf("Shalini Vashishtha \n 2200970100152 Program 9\n"); printf("Maximum value
inBinary Knapsack = %d\n", maxValue); // Print the result
return 0;
Output :
Program No. - 10
Problem Statement: Find Minimum Cost Spanning Tree using
a.Kruskal`s Algorithm
b.Prims Algorithm
Description:
Kruskal's Algorithm is used to find the minimum spanning tree for a connected weighted graph.
The main target of the algorithm is to find the subset of edges by using which we can traverse
every vertex of the graph. It follows the greedy approach that finds an optimum solution at every
stage instead of focusing on a global optimum. O(E log E) is the Time complexity.
Algorithm :
Step 1: Create a forest F in such a way that every vertex of the graph is a separate
tree.
Step 2: Create a set E that contains all the edges of the graph.
Step 3: Repeat Steps 4 and 5 while E is NOT EMPTY and F is not spanning
Step 4: Remove an edge from E with minimum weight
Step 5: IF the edge obtained in Step 4 connects two different trees, then add it to
ELSE
Discard the edge
Step 6: END
Program:
#include <stdio.h> #include <stdlib.h> struct Edge { int src, dest, weight;
};
struct Graph {
int V, E;
struct Edge* edges;
};
struct Subset {
int parent; int
rank;
};
struct Graph* createGraph(int V, int E) { struct Graph* graph =
(struct Graph*)malloc(sizeof(struct Graph)); graph->V = V;
graph->E = E; graph->edges = (struct Edge*)malloc(E *
sizeof(struct Edge)); return graph;
}
int find(struct Subset subsets[], int i) { if
(subsets[i].parent != i) subsets[i].parent =
find(subsets, subsets[i].parent); return
subsets[i].parent;
}
void Union(struct Subset subsets[], int x, int y) {
int xroot = find(subsets, x); int yroot =
find(subsets, y); if (subsets[xroot].rank <
subsets[yroot].rank) subsets[xroot].parent =
yroot; else if (subsets[xroot].rank >
subsets[yroot].rank) subsets[yroot].parent =
xroot;
else {
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
int compareEdges(const void* a, const void* b) {
struct Edge* edge1 = (struct Edge*)a; struct
Edge* edge2 = (struct Edge*)b; return edge1-
>weight - edge2->weight;
}
Union(subsets, x, y);
totalWeight += result[i].weight;
}
int main() {
Output :
Prims Algorithm
Description:
Prim's Algorithm is a greedy algorithm that is used to find the minimum spanning
tree from a graph. Prim's algorithm finds the subset of edges that includes every
vertex of the graph such that the sum of the weights of the edges can be
minimized. O((V + E) log V) is the time complexity.
Algorithm:
Step 1: Select a starting vertex
Step 2: Repeat Steps 3 and 4 until there are fringe vertices
Step 3: Select an edge 'e' connecting the tree vertex and fringe vertex that has
minimum weight
Step 4: Add the selected edge and the vertex to the minimum spanning tree T
[END OF LOOP]
Step 5: EXIT
Program:
#include <stdio.h>
#include <limits.h>
#define V 5
minIndex = v;
return minIndex;
}
in MST
included[i] = 0;
// The MST will have V - 1 edges for (int count = 0; count < V - 1;
key[v] = graph[u][v];
}
}
printf("Edge \tWeight\n");
parent[i], i, graph[i][parent[i]]);
}}
2200970100152");int graph[V][V] = {
{0, 2, 0, 8, 0},
{2, 0, 4, 8, 5},
{0, 3, 0, 0, 9},
{6, 5, 0, 0, 9},
{0, 5, 7, 9, 0}
};
Output :
Program No. - 11
Problem Statement: a given vertex in a weighted connected graph, find shortest paths to
other vertices using Dijkstra’s algorithm.
Description: Dijkstra's Algorithm. Dijkstra's Algorithm is a Graph algorithm that finds the
shortest path from a source vertex to all other vertices in the Graph (single source shortest
path). It is a type of Greedy Algorithm that only works on Weighted Graphs having positive
weights. The time complexity of Dijkstra's Algorithm is O(V2) with the help of the adjacency
matrix representation of the graph. This time complexity can be reduced to O((V + E) log V) with
the help of an adjacency list representation of the graph, where V is the number of vertices and
E is the number of edges in the graph.
Algorithm:
Step 1: First, we will mark the source node with a current distance of 0 and set the rest of the
nodes to INFINITY.
Step 2: We will then set the unvisited node with the smallest current distance as the current
node, suppose X.
Step 3: For each neighbor N of the current node X: We will then add the current distance of X
with the weight of the edge joining X-N. If it is smaller than the current distance of N, set it as
Step 5: We will repeat the process from 'Step 2' if there is any node unvisited left in the graph.
Program:
#include <stdio.h>
#include <limits.h>
v;}
return minIndex;
}
dist[src] = 0; // Distance from source to itself is
graph[u][v]; parent[v] = u;
temp = parent[temp];
printf("\n");
};
dijkstra(graph, 0);
return 0;
Output :
Program No. - 12
Problem Statement: Implement All Pairs Shortest Paths problem using Floyd’s algorithm
Description: The Floyd-Warshall algorithm is a dynamic programming algorithm used to
discover the shortest paths in a weighted graph, which includes negative weight cycles. The
algorithm works with the aid of computing the shortest direction between every pair of vertices
within the graph, the usage of a matrix of intermediate vertices to keep music of the
exceptional-recognized route thus far.
Algorithm:
FloydWarshall(graph)
Output: dist[][] - matrix containing shortest path distances between all pairs of
vertices
1. Initialize:
For i from 0 to n-
1: For j from 0
to n-1:
Program:
#include <stdio.h>
#define V 4
int dist[V][V];
dist[i][j] = graph[i][j];
if (dist[i][j] == INF) {
printf("%7s", "INF");
} else {
printf("%7d", dist[i][j]);
printf("\n");
2200970100152");int graph[V][V] = {
{5, 0, 2, INF},
};
floydWarshall(graph);
return 0;
}
Output:
Program No – 13
Problem Statement: Write program to Implement Travelling Sales problem using Dynamicprogramming.
Description: The traveling salesman problems abide by a salesman and a set of cities. The
salesman has to visit every one of the cities starting from a certain one (e.g., the hometown)
and to return to the same city. The challenge of the problem is that the traveling salesman
needs to minimize the total length of the trip.
Algorithm:
Step 1: Firstly, we will consider City 1 as the starting and ending point. Since the route is cyclic,
Step 2: As the second step, we will generate all the possible permutations of the cities, which are
(n-1)!
Step 3: After that, we will find the cost of each permutation and keep a record of the minimum
cost permutation.
Program:
#include<stdio.h>
#include<limits.h>
#define V 4
(mask == (1 << V) - 1)
{ return
dist[pos][0];
if (dp[mask][pos] != -1) {
return dp[mask][pos];
no.-2200970100152n");
};
j++) { dist[i][j] =
graph[i][j];}}
}}
Output :
Program No. – 14
Problem Statement: Design and implement to find a subset of a given set S = {s1,s2,…,sn} of
n positive integer whose SUM is equal to a given positive integer d.
For example, if S = {1,2,5,6,8} and d = 9 there are two solutions {1,2,6}. Display a suitable
message, if the given problem instance doesn’t have solution.
Description: The set cover problem is to find the smallest sub-collection of S whose union
equals the universe given a set of elements 1, 2,..., n (referred to as the universe) and a
collection S of m sets. For instance, take the universe U = 1, 2, 3, 4, 5 and the group of sets S =
1, 2, 3, 2, 4, 3, and 4. The merger of S is undoubtedly U. The following lesser number of sets,
however, may accommodate all elements: 1, 2, 3, and 4.
Program:
#include <stdio.h> int
if (j == 0) { dp[i][j]
= 1; } else if (i == 0) {
dp[i][j] = 0;
} else {
}
}
if (dp[n][d] == 0) {
printf("No solution
exists\n"); return 0;
j -= S[i - 1];
{ printf(", ");
printf("}\n");
return 1;
}
int main() {
2200970100152");
sizeof(S) / sizeof(S[0]);
findSubset(S, n, d);
return 0;
Output:
Program No. – 15
Problem Statement: Design and implement to find all Hamiltonian Cycles in a connected
undirected Graph G of n vertices using backtracking principle.
Description: A Hamiltonian Cycle (or Hamiltonian Circuit) in a graph is a cycle that visits each
vertex exactly once and returns to the starting vertex. This problem involves determining if such
a cycle exists in a given graph.
Program:
#include<stdio.h>
(graph[path[pos-1]][v] == 0) return
(graph[path[pos-1]][path[0]] == 1)
return
1; else
return 0;
}
for (int v = 1; v < V; v++) { if
path[pos] = v; if
return 1;
path[pos] = -1;
return 0;
printf("Memory allocation
failed\n"); return 0;
(hamCycleUtil(graph, path, 1) ==
0) { printf("\nSolution does
return 0;
}
printSolution(path
); free(path);
return 1;
printf("\n");
no.-2200970100152");
{1, 0, 1, 1, 1},
{1, 1, 0, 1, 0},
{0, 1, 1, 0,
1}, {1, 1, 0,
1, 0},
};
hamCycle(graph1); int
graph2[V][V] = {{0, 1, 0, 1,
0},
{1, 0, 1, 1, 0},
{0, 1, 0, 0, 1},
{1, 1, 0, 0,
0}, {0, 0, 1,
0, 0},
};
hamCycle(graph2);
return 0;
Output:
Program No. – 16
Problem Statement: Implement n-Queen Problem.
Description: In N-Queen problem, we are given an NxN chessboard and we have to place
N number of queens on the board in such a way that no two queens attack each other. A queen
will attack another queen if it is placed in horizontal, vertical or diagonal points in its way. The
most popular approach for solving the N Queen puzzle is Backtracking.
Algorithm:
• Place the first queen in the top-left cell of the chessboard.
• After placing a queen in the first cell, mark the position as a part of the solution and then
recursively check if this will lead to a solution.
• Now, if placing the queen doesn’t lead to a solution. Then go to the first step and place queens
in other cells. Repeat until all cells are tried.
Program:
#include<stdio.h>
#define BOARD_SIZE 6 // Modified board
chBoard[BOARD_SIZE][BOARD_SIZE]) { for
printf("\n");
}
}
int isQueenPlaceValid(int chBoard[BOARD_SIZE][BOARD_SIZE], int crntRow, int crntCol) {
for (int i = 0; i <
crntCol; i++)if
(chBoard[crntRow][i])
if (chBoard[i][j])
i++, j--)
if
(chBoard[i][j])
return 0;
return 1;
}
int solveProblem(int chBoard[BOARD_SIZE][BOARD_SIZE], int crntCol) {
if (crntCol >= BOARD_SIZE)
BOARD_SIZE; i++) { if
(isQueenPlaceValid(chBoard, i,
crntCol)) {
chBoard[i][crntCol] = 1; if
(solveProblem(chBoard, crntCol +
1))
return 1;
chBoard[i][crntCol] = 0;
}
}
return
0;
}
int displaySolution() { int
chBoard[BOARD_SIZE][BOARD_
chBoard[i][j] = 0; if
(solveProblem(chBoard, 0) ==
0) { printf("Solution
0;
displayChess(chBoard);
return 1;
}
int main() { printf("Name- Shalini Vashishtha \nRoll
no.-2200970100152");
displaySolution();
return 0;
Output :
Program No. – 17
Description: In its simplest form, it is a way of coloring the vertices of a graph such that no
two adjacent vertices are of the same color; this is called vertex coloring.
Algorithm:
Input a graph with V vertices (represented by an adjacency matrix graph[V][V]) and an integer m
for the maximum number of colors. Initialize a color array
color [] of size V, setting all values to 0 (no color). For each vertex v, try assigning
each color from 1 to m. Check if the color is safe (no adjacent vertex has the same color). If the
color is safe, assign it to the vertex and move to the next vertex. If all
vertices are successfully colored, print the solution. If a color can't be assigned to a vertex,
backtrack to the previous vertex and try a different color. If a valid coloring is found, output the
colors; otherwise, print "Solution does not exist."
Program:
#include <stdio.h>
#include <stdlib.h>
color[i]);
}
int isSafe(int v, int graph[V][V], int
return 0;
return 1;
if (v == V) {
return 1;
= c; if (graphColoringUtil(graph, m,
color, v + 1)) {
return 1;
color[v] = 0;
return 0;
}
int graphColoring(int graph[V][V],
0;
if (graphColoringUtil(graph, m, color, 0)
exist\n"); free(color);
return 0;
printSolution(colo
r); free(color);
return 1;
no.-2200970100152");
int graph[V][V] = {
{0, 1, 1, 0, 0},
{1, 0, 1, 1, 0},
{1, 1, 0, 1, 1},
{0, 1, 1, 0, 1},
{0, 0, 1, 1, 0}
};
if (!graphColoring(graph, m)) {
exist.\n");
return 0;
Output: