0% found this document useful (0 votes)
61 views28 pages

Dynamic Programming

The document describes implementing dynamic programming algorithms to solve various optimization problems. It discusses implementing multi-stage graph problems using forward and backward methods, all pairs shortest path using Floyd-Warshall algorithm, single source shortest path using Bellman-Ford algorithm, optimal binary search tree problem, and 0/1 knapsack problem. It provides pseudocode for the multi-stage graph algorithms and analyzes their time and space complexity.

Uploaded by

Amisha Sharma
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
0% found this document useful (0 votes)
61 views28 pages

Dynamic Programming

The document describes implementing dynamic programming algorithms to solve various optimization problems. It discusses implementing multi-stage graph problems using forward and backward methods, all pairs shortest path using Floyd-Warshall algorithm, single source shortest path using Bellman-Ford algorithm, optimal binary search tree problem, and 0/1 knapsack problem. It provides pseudocode for the multi-stage graph algorithms and analyzes their time and space complexity.

Uploaded by

Amisha Sharma
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 28

Experiment No.

3: DYNAMIC PROGRAMMING
Date:24/03/2023

Aim: Write a C program to implement the following program using Dynamic programming
a. Multi stage graph
b. All pair shortest path :Floyd Warshall
c. Single Source Shortest Path : Bellman Ford algorithm
d. Optimal binary search tree
e. 0/1 knapsack problem

THEORY:
Dynamic programming:

Dynamic programming is a technique that breaks the problems into sub-problems, and saves
the result for future purposes so that we do not need to compute the result again. The
subproblems are optimized to optimize the overall solution is known as optimal substructure
property. The main use of dynamic programming is to solve optimization problems. Here,
optimization problems mean that when we are trying to find out the minimum or the
maximum solution of a problem. The dynamic programming guarantees to find the optimal
solution of a problem if the solution exists.

The definition of dynamic programming says that it is a technique for solving a complex
problem by first breaking into a collection of simpler subproblems, solving each subproblem
just once, and then storing their solutions to avoid repetitive computations.

The following are the steps that the dynamic programming follows:

o It breaks down the complex problem into simpler subproblems.


o It finds the optimal solution to these sub-problems.
o It stores the results of subproblems (memoization). The process of storing the results
of subproblems is known as memorization.
o It reuses them so that same sub-problem is calculated more than once.
o Finally, calculate the result of the complex problem.

The above five steps are the basic steps for dynamic programming. The dynamic
programming is applicable that are having properties such as:

Those problems that are having overlapping subproblems and optimal substructures. Here,
optimal substructure means that the solution of optimization problems can be obtained by
simply combining the optimal solution of all the subproblems.

In the case of dynamic programming, the space complexity would be increased as we are
storing the intermediate results, but the time complexity would be decreased.

Roll No. 211105036 |Page


a) MULTISTAGE GRAPH
Date:24/03/2023
Problem Statement:

(i) Write a c program to implement a Multistage graph algorithm : Forward Method


on following graph:
(ii) Write a c program to implement a Multistage graph algorithm : Backward
Method on following graph.

Algorithm
I] forward graph

Roll No. 211105036 |Page


II]backward graph

TIME AND SPACE COMPLEXITY :

Time complexity :

The time complexity of solving the multistage graph problem using dynamic programming is
typically O(V^2), where V is the number of vertices (nodes) in the graph.

In the dynamic programming approach for the multistage graph problem, we iterate over
each vertex and calculate the optimal cost based on the costs of its successors. This process
involves considering all possible outgoing edges from each vertex.

Since there are V vertices in the graph, the outer loop runs V times. For each vertex, we need
to consider all possible outgoing edges, which can be up to V-1 edges in the worst case (if
every vertex is connected to all subsequent stages). Therefore, the inner loop also runs V-1
times.

As a result, the time complexity of the dynamic programming approach for the multistage
graph problem is O(V * (V-1)), which simplifies to O(V^2) asymptotically.

Space Complexity :
The space complexity for the dynamic programming approach to the multistage graph
problem depends on the specific implementation. However, in general, the space complexity
is typically O(V), where V is the number of vertices (nodes) in the graph.

Roll No. 211105036 |Page


In the dynamic programming approach, we often use a table or an array to store the optimal
costs for each vertex at each stage. The table is usually a one-dimensional array with V
elements, where each element represents the minimum cost for the corresponding vertex.

Additionally, we might need additional arrays or data structures to store intermediate results
or track the optimal path. The space required for these additional data structures is typically
small compared to the main table, and thus, the overall space complexity remains O(V).

It's worth noting that if the multistage graph is represented by an adjacency matrix or
adjacency list, the space complexity for storing the graph itself can be O(V^2) or O(V + E),
respectively, where E is the number of edges in the graph. However, the space complexity of
the dynamic programming algorithm specifically refers to the additional space used by the
algorithm itself, not the input graph representation.

Code :
Program (i):
/* Code for multistage graph: Forward Method */
#include <stdio.h>
int adj[100][100], C[100][100], p[100], cost[100], d[100];

void accept_graph(int n, int k)


{
int max_edges = n * (n - 1);
int origin, destin, edgecost;
printf("Enter the edges of the graph and their respective cost.\
n");
for (int i = 0; i < max_edges; i++)
{
printf("Enter the edge,( 0 0 randval) to quit :");
scanf("%d %d %d", &origin, &destin, &edgecost);

if ((origin == 0) && (destin == 0))


break;
if (origin > n || destin > n || origin <= 0 || destin <= 0)
{
printf("Invalid edge.\n");
i--;
}
else
{
adj[origin - 1][destin - 1] = 1;
C[origin - 1][destin - 1] = edgecost;
}
}
}
void init_cost(int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
C[i][j] = __INT32_MAX__;
}
}
void fgraph(int n, int k, int v)
{
for (int i = 0; i < n; i++)
{
cost[i] = __INT32_MAX__;

Roll No. 211105036 |Page


d[i] = 0;
}
cost[n - 1] = 0;
for (int j = n - 1; j >= 0; j--)
{
int min = __INT32_MAX__, minr;
for (int r = j + 1; r < n; r++)
{
if (adj[j][r] == 1 && (C[j][r] + cost[r]) < min)
{
min = C[j][r] + cost[r];
minr = r;
}
}
if (min != __INT32_MAX__)
cost[j] = min;
d[j] = minr;
}
p[0] = v - 1;
p[k - 1] = n - 1;
for (int j = 1; j < k - 1; j++)
p[j] = d[p[j - 1]];
}
int main()
{
// FILE *fp;
// fp = fopen("graph3.txt", "r+");
int n, k;
printf("Enter the number of vertices of the graph, and the
stages.\n");
scanf("%d%d", &n, &k);
init_cost(n);
accept_graph(n, k);
// accept_graph(fp, n, k);
// fclose(fp);
int v;
printf("Enter the source vertex of the graph.\n");
scanf("%d", &v);
fgraph(n, k, v);
printf("VERTEX COST CHOICE VERTEX\n");
printf("%2d %2d \n", n, cost[n - 1]);
for (int i = n - 2; i >= 0; i--)
{
printf("%2d %2d %2d", i + 1, cost[i], d[i] +
1);
printf("\n");
}
printf("The chosen minimun cost path is: ");
for (int i = 0; i < k; i++)
printf("%d ", p[i] + 1);
printf("\n");
return 0;
}

OUTPUT :
PS D:\SE SEM IV\MADF LAB> gcc fgraph.c
PS D:\SE SEM IV\MADF LAB> ./a.exe
Enter the number of vertices of the graph, and the stages.
12
5
Enter the edges of the graph and their respective cost.
Enter the edge,( 0 0 randval) to quit :1 2 3
Enter the edge,( 0 0 randval) to quit :1 3 8
Enter the edge,( 0 0 randval) to quit :1 4 4

Roll No. 211105036 |Page


Enter the edge,( 0 0 randval) to quit :1 5 5
Enter the edge,( 0 0 randval) to quit :2 6 4
Enter the edge,( 0 0 randval) to quit :2 7 3
Enter the edge,( 0 0 randval) to quit :3 6 5
Enter the edge,( 0 0 randval) to quit :3 7 4
Enter the edge,( 0 0 randval) to quit :4 7 3
Enter the edge,( 0 0 randval) to quit :4 8 2
Enter the edge,( 0 0 randval) to quit :5 7 2
Enter the edge,( 0 0 randval) to quit :5 8 1
Enter the edge,( 0 0 randval) to quit :6 9 3
Enter the edge,( 0 0 randval) to quit :6 10 4
Enter the edge,( 0 0 randval) to quit :7 9 4
Enter the edge,( 0 0 randval) to quit :7 10 7
Enter the edge,( 0 0 randval) to quit :7 11 6
Enter the edge,( 0 0 randval) to quit :8 10 6
Enter the edge,( 0 0 randval) to quit :8 11 7
Enter the edge,( 0 0 randval) to quit :9 12 3
Enter the edge,( 0 0 randval) to quit :10 12 1
Enter the edge,( 0 0 randval) to quit :11 12 4
Enter the edge,( 0 0 randval) to quit :0 0 1
Enter the source vertex of the graph.
1
VERTEX COST CHOICE VERTEX
12 0
11 4 12
10 1 12
9 3 12
8 7 10
7 7 9
6 5 10
5 8 8
4 9 8
3 10 6
2 9 6
1 12 2
The chosen minimun cost path is: 1 2 6 10 12
PS D:\SE SEM IV\MADF LAB>

Program (ii):
/* Code for multistage graph: Backward Method */
#include <stdio.h>
int adj[100][100], C[100][100], p[100], bcost[100], d[100];

void accept_graph(int n, int k)


{
int max_edges = n * (n - 1);
int origin, destin, edgecost;
printf("Enter the edges of the graph and their respective cost.\
n");
for (int i = 0; i < max_edges; i++)
{
printf("Enter the edge,( 0 0 randval) to quit :");
scanf("%d %d %d", &origin, &destin, &edgecost);

if ((origin == 0) && (destin == 0))


break;
if (origin > n || destin > n || origin <= 0 || destin <= 0)

Roll No. 211105036 |Page


{
printf("Invalid edge.\n");
i--;
}
else
{
adj[origin - 1][destin - 1] = 1;
C[origin - 1][destin - 1] = edgecost;
}
}
}
void init_cost(int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
C[i][j] = __INT32_MAX__;
}
}
void bgraph(int n, int k, int v)
{
for (int i = 0; i < n; i++)
{
bcost[i] = __INT32_MAX__;
d[i] = 0;
}
bcost[0] = 0;
for (int j = 0; j < n; j++)
{
int min = __INT32_MAX__, minr;
for (int r = j - 1; r >= 0; r--)
{
if (adj[r][j] == 1 && (C[r][j] + bcost[r]) < min)
{
min = C[r][j] + bcost[r];
minr = r;
}
}
if (min != __INT32_MAX__)
bcost[j] = min;
d[j] = minr;
}
p[0] = v - 1;
p[k - 1] = n - 1;
for (int j = k - 2; j > 0; j--)
p[j] = d[p[j + 1]];
}
int main()
{
// FILE *fp;
// fp = fopen("graph3.txt", "r+");
int n, k;
printf("Enter the number of vertices of the graph, and the
stages.\n");
scanf("%d%d", &n, &k);
init_cost(n);
accept_graph(n, k);
// accept_graph(fp, n, k);
// fclose(fp);
int v;
printf("Enter the source vertex of the graph.\n");
scanf("%d", &v);
bgraph(n, k, v);
printf("VERTEX COST CHOICE VERTEX\n");
printf("%2d %2d \n", 1, bcost[1 - 1]);
for (int i = 1; i < n; i++)
{

Roll No. 211105036 |Page


printf("%2d %2d %2d", i + 1, bcost[i], d[i] +
1);
printf("\n");
}
printf("The chosen minimun cost path is: ");
for (int i = 0; i < k; i++)
printf("%d ", p[i] + 1);
printf("\n");
return 0;
}

OUTPUT :

PS D:\SE SEM IV\MADF LAB> gcc fgraph.c


PS D:\SE SEM IV\MADF LAB> ./a.exe
Enter the number of vertices of the graph, and the stages.
12
5
Enter the edges of the graph and their respective cost.
Enter the edge,( 0 0 randval) to quit :1 2 3
Enter the edge,( 0 0 randval) to quit :1 3 8
Enter the edge,( 0 0 randval) to quit :1 4 4
Enter the edge,( 0 0 randval) to quit :1 5 5
Enter the edge,( 0 0 randval) to quit :2 6 4
Enter the edge,( 0 0 randval) to quit :2 7 3
Enter the edge,( 0 0 randval) to quit :3 6 5
Enter the edge,( 0 0 randval) to quit :3 7 4
Enter the edge,( 0 0 randval) to quit :4 7 3
Enter the edge,( 0 0 randval) to quit :4 8 2
Enter the edge,( 0 0 randval) to quit :5 7 2
Enter the edge,( 0 0 randval) to quit :5 8 1
Enter the edge,( 0 0 randval) to quit :6 9 3
Enter the edge,( 0 0 randval) to quit :6 10 4
Enter the edge,( 0 0 randval) to quit :7 9 4
Enter the edge,( 0 0 randval) to quit :7 10 7
Enter the edge,( 0 0 randval) to quit :7 11 6
Enter the edge,( 0 0 randval) to quit :8 10 6
Enter the edge,( 0 0 randval) to quit :8 11 7
Enter the edge,( 0 0 randval) to quit :9 12 3
Enter the edge,( 0 0 randval) to quit :10 12 1
Enter the edge,( 0 0 randval) to quit :11 12 4
Enter the edge,( 0 0 randval) to quit :0 0 1
Enter the source vertex of the graph.
1
VERTEX COST CHOICE VERTEX
12 0
11 4 12
10 1 12
9 3 12
8 7 10
7 7 9
6 5 10
5 8 8
4 9 8
3 10 6
2 9 6

Roll No. 211105036 |Page


1 12 2
The chosen minimun cost path is: 1 2 6 10 12
PS D:\SE SEM IV\MADF LAB>

b) ALL PAIR SHORTEST PATH

Date:28/03/2023
Problem Statement:

Write a c program to implement a all pair shortest path algorithm on the following graph:

Algorithm

Time and space complexity :

Time complexity :

Roll No. 211105036 |Page


The time complexity of the dynamic programming approach for solving the all-pairs shortest
path problem is typically O(V^3), where V is the number of vertices (nodes) in the graph.

In the dynamic programming approach, we build a table or matrix to store the shortest
distances between all pairs of vertices. The algorithm iterates over each vertex as an
intermediate node and updates the shortest distances between all pairs of vertices based on
the intermediate node.

There are typically three nested loops involved in this process. The outermost loop selects the
intermediate vertex, the middle loop selects the source vertex, and the innermost loop selects
the destination vertex. Each loop iterates V times, as we need to consider each vertex as a
potential intermediate, source, or destination vertex.

Hence, the overall time complexity of the dynamic programming approach for all-pairs
shortest path is O(V^3). However, it's important to note that there are more efficient
algorithms available for specific cases, such as the Floyd-Warshall algorithm, which can
achieve the same result with a time complexity of O(V^3) as well.

Space complexity :
The space complexity of the dynamic programming approach for solving the all-pairs
shortest path problem is typically O(V^2), where V is the number of vertices (nodes) in the
graph.
In the dynamic programming approach, we use a matrix to store the shortest distances
between all pairs of vertices. The matrix has dimensions V x V, representing the distances
from each source vertex to each destination vertex.
Therefore, the space required to store the matrix is O(V^2), as it grows quadratically with the
number of vertices in the graph.
Additionally, if we also need to store the predecessor information to reconstruct the shortest
paths, an additional matrix of the same size, i.e., V x V, would be required. This would
further contribute to the space complexity.
Overall, the space complexity of the dynamic programming approach for all-pairs shortest
path is O(V^2) due to the space required for the distance matrix and potentially the
predecessor matrix.

Code
#include <stdio.h>
#include <limits.h>
#define sint(x) scanf("%d", &x);
#define N 30
#define inf 99999

void fillinf(int a[][N], int n)


{
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
a[i][j] = inf;
}

void fillz(int a[][N], int n)


{
for (int i = 0; i < n; i++)

Roll No. 211105036 |Page


for (int j = 0; j < n; j++)
if (i == j)
a[i][j] = 0;
}

void getmat(int a[][N], int n)


{
int w, x, y;
// printf("Enter -1 -1 to exit: ");
for (int i = 0; i < n * (n - 1); i++)
{
sint(x);
sint(y);
if (x == -1 && y == -1)
return;
// printf("Enter weight: ");
sint(w);
a[--x][--y] = w;
}
}

int _min(int a, int b)


{
return a < b ? a : b;
}

void allpair(int cost[][N], int a[][N], int n)


{
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cost[i][j] = a[i][j];
fillz(cost, n);
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (cost[i][k] + cost[k][j] < cost[i][j])
cost[i][j] = cost[i][k] + cost[k][j];
}
}

void showmat(int a[][N], int n)


{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (a[i][j] == inf)
printf("inf ");
else
printf("%d ", a[i][j]);
}
printf("\n");
}
}

int main(int argc, char const *argv[])


{
int cost[N][N], a[N][N], n;
sint(n);
fillinf(a, n);
getmat(a, n);
allpair(cost, a, n);
printf("The shortest path matrix is\n");
showmat(cost, n);
return 0;
}

Roll No. 211105036 |Page


OUTPUT :
PS D:\SE SEM IV\MADF LAB> gcc allpair.c
PS D:\SE SEM IV\MADF LAB> ./a.exe
4
1 2 5
1 3 9
2 3 1
3 4 2
4 2 3
-1 -1
The shortest path matrix is
0 5 6 8
inf 0 1 3
inf 5 0 2
inf 3 4 0
PS D:\SE SEM IV\MADF LAB>

Roll No. 211105036 |Page


c) Single Source Shortest Path (Bellman Ford Algorithm)
Date:28/03/2023
Problem Statement:

Write a c program to find shortest path using bellman ford algorithm on following graph:

ALGORITHM :

Time and space complexity :

Time complexity :
The time complexity of the Bellman-Ford algorithm for finding the shortest path in a graph is
typically O(V * E), where V is the number of vertices (nodes) and E is the number of edges
in the graph.

Roll No. 211105036 |Page


In the Bellman-Ford algorithm, we relax each edge in the graph V-1 times to find the shortest
paths from the source vertex to all other vertices. In each relaxation step, we check if
updating the distance through the current edge yields a shorter path to the destination vertex.
This process is repeated V-1 times to ensure that the shortest distances are propagated
through the graph.
Since we need to relax each edge V-1 times, the total number of iterations is V-1. For each
iteration, we consider all the edges in the graph. Hence, the time complexity of the algorithm
is O(V * E).
It's worth noting that if the graph is a dense graph (E ~ V^2), the time complexity can be
expressed as O(V^3). However, in the worst-case scenario, where the graph is a complete
graph, the number of edges can be as high as E = V*(V-1)/2, leading to a time complexity of
O(V^3).

Space complexity :
The space complexity of the Bellman-Ford algorithm for finding the shortest path in a graph
is typically O(V), where V is the number of vertices (nodes) in the graph.
The algorithm uses an array or list to store the distances from the source vertex to each vertex
in the graph. This array has a length of V, representing the distances for each vertex.
In addition to the distance array, the algorithm may also use other data structures to store
auxiliary information, such as the predecessor of each vertex in the shortest path. The space
required for these additional data structures is typically small compared to the main distance
array and does not significantly affect the overall space complexity.
Therefore, the space complexity of the Bellman-Ford algorithm is O(V) due to the space
required for the distance array and any additional auxiliary data structures.

Code
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>

struct Edge
{
int source;
int destination;
struct Egde *next;
};

struct Edge *HEAD=NULL;


void Insert_Edge(int, int);

int main()
{
int vertices;
vertices = 5;
int graph[vertices][vertices];

for(int i=0;i<vertices;i++)
{
for(int j=0;j<vertices;j++)
{
graph[i][j]=INT_MAX;
}
}

Roll No. 211105036 |Page


graph[1][2]=4;
graph[2][4]=-3;
graph[2][3]=8;
graph[1][3]=6;
graph[5][1]=2;
graph[3][5]=11;
graph[5][4]=8;

printf("GRAPH AFTER FILLING THE NODE IS :::\n");


for(int i=0;i<vertices;i++)
{
for(int j=0;j<vertices;j++)
{
if(graph[i][j] == INT_MAX)
{
printf("%-10c", '-');
}
else
{
printf("%-10d", graph[i][j]);
}
}
printf("\n");
}

printf("************************************************************
**********\n");
// Inserting edges in the linked list.
for(int i=0;i<vertices;i++)
{
for(int j=0;j<vertices;j++)
{
if(graph[i][j] != INT_MAX)
{
Insert_Edge(i,j);
}
}
}
int source;
printf("Enter the source node:: ");

scanf("%d",&source);
int shortest_path[vertices];
for(int i=0;i<vertices;i++)
{
shortest_path[i]=INT_MAX;
}
shortest_path[source]=0;
for(int i=1;i<vertices;i++)
{
struct Edge *temp=HEAD;
while(temp!=NULL)
{

if(shortest_path[temp->source] != INT_MAX)
{
if(shortest_path[temp->source] + graph[temp->source]
[temp->destination]
< shortest_path[temp->destination])
{
shortest_path[temp-
>destination]=shortest_path[temp->source]
+ graph[temp->source][temp->destination];
}
}
temp= temp->next;

Roll No. 211105036 |Page


}
}
printf("MINUMUM COSTS FOUND AFTER APPLYING THE BELLMAN FORD
ALGORITHM FOR SOURCE NODE [%c] COMES OUT TO BE::: \n",source+97);

printf("************************************************************
*****\n");
for(int i=0;i<vertices;i++)
{
if(shortest_path[i]==INT_MAX)
{
printf("Node [%c] to [%c] is unreachable \
n",source+97,i+97);
continue;
}
else
{
printf("Node [%c] TO [%c] MINIMUM COST IS:: %d\
n",source+97,i+97,shortest_path[i]);
}
}
return 0;
}
void Insert_Edge(int src, int des)
{
struct Edge *ptr = (struct Edge*)malloc(sizeof(struct Edge));
struct Edge *temp=HEAD;
ptr->source=src;
ptr->destination=des;
if(HEAD==NULL)
{
HEAD=ptr;
HEAD->next=NULL;
}
else
{
while(temp->next!=NULL)
{
temp=(struct Edge*)temp->next;
}
temp->next=ptr;
ptr->next=NULL;
}
return ;
}

OUTPUT :

PS D:\SE SEM IV\MADF LAB> gcc bellman.c


PS D:\SE SEM IV\MADF LAB> ./a.exe
GRAPH AFTER FILLING THE NODE IS :::
- - - - -
- - 4 6 -
- - - 8 -3
- - - - -
11 - - - -
********************************************************************
Enter the source node:: 1
MINUMUM COSTS FOUND AFTER APPLYING THE BELLMAN FORD ALGORITHM FOR
SOURCE NODE [b] COMES OUT TO BE:::
*****************************************************************
Node [b] TO [a] MINIMUM COST IS:: 12
Node [b] TO [b] MINIMUM COST IS:: 0

Roll No. 211105036 |Page


Node [b] TO [c] MINIMUM COST IS:: 4
Node [b] TO [d] MINIMUM COST IS:: 6
Node [b] TO [e] MINIMUM COST IS:: 1
PS D:\SE SEM IV\MADF LAB
d) OPTIMAL BINARY SEARCH TREE
Date:06/04/2023
Problem Statement:
Write a c program to implement a optimal binary search tree on the give values

N=5

a1,a2,a3,a4,a5{apr,mar,may,oct,sept}

p1,p2,p3,p4,p5= {3,4,3,2,4}

q0,q1,q2,q3,q4,q5={4,4,5,4,5,4}

Algorithm

Roll No. 211105036 |Page


TIME AND SPACE COMPLEXITY :

Time complexity :

The time complexity of constructing an optimal binary search tree using dynamic
programming is typically O(n^3), where n is the number of keys in the search tree.
In the dynamic programming approach, we build a table or matrix to store the optimal costs
for subtrees of the binary search tree. The algorithm iterates over different subtree sizes and
considers all possible roots for each subtree.
There are typically two nested loops involved in this process. The outer loop determines the
size of the subtree, ranging from 1 to n (the number of keys). The inner loop selects the
starting index of the subtree within the list of keys.
For each combination of subtree size and starting index, the algorithm performs calculations
that involve considering all possible roots within the subtree and computing the optimal cost
based on the previously computed values.

Roll No. 211105036 |Page


The time complexity of the dynamic programming approach arises from the three nested
levels of iteration: the outer loop iterating n times, the middle loop iterating n times, and the
inner loop iterating n times. Hence, the overall time complexity is O(n^3).

It's worth noting that there are variations and optimizations to the algorithm that can improve
its efficiency in certain cases, such as using memoization or applying additional heuristics.
However, the basic dynamic programming approach has a time complexity of O(n^3).

Space complexity ;

The space complexity of constructing an optimal binary search tree using dynamic
programming is typically O(n^2), where n is the number of keys in the search tree.
In the dynamic programming approach, we build a table or matrix to store the optimal costs
for subtrees of the binary search tree. The table has dimensions n x n, representing the
different combinations of subtree sizes and starting indices.
Additionally, we may use additional arrays or data structures to store auxiliary information,
such as the probabilities or frequencies of the keys, or to track the optimal tree structure. The
space required for these additional data structures is typically small compared to the main
table and does not significantly affect the overall space complexity.
Therefore, the space complexity of the optimal binary search tree construction algorithm
using dynamic programming is O(n^2) due to the space required for the main table or matrix
and any additional auxiliary data structures.

Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#define MAX 100
char iden[MAX][MAX];
int p[MAX], q[MAX];
int printlchild(int r[MAX][MAX], int i, int j, int level)
{
if (r[i][r[i][j] - 1] != 0)
{
if (level == 0)
printf("%d = %s ", r[i][r[i][j] - 1], iden[r[i][r[i][j]
- 1]]);
return 1;
}
return 0;
}
int printrchild(int r[MAX][MAX], int i, int j, int level)
{
if (r[r[i][j]][j] != 0)
{
if (level == 0)
printf("%d = %s ", r[r[i][j]][j], iden[r[r[i][j]][j]]);
return 1;
}
return 0;
}
void printchild(int r[MAX][MAX], int i, int j, int n, int level)
{
int a, b;
a = printlchild(r, i, j, level);
b = printrchild(r, i, j, level);

Roll No. 211105036 |Page


if (a != 0 && level > 0)
printchild(r, i, r[i][j] - 1, n, level - 1);
if (b != 0 && level > 0)
printchild(r, r[i][j], j, n, level - 1);
}
void levelorder(int r[MAX][MAX], int i, int j, int n)
{
for (int level = 0; level < n - 1; level++)
{
printchild(r, i, j, n, level);
printf("\n");
}
}
void OBST(int w[MAX][MAX], int c[MAX][MAX], int r[MAX][MAX], int n)
{
int temp = 0, min, min1;
for (int i = 0; i < n; i++)
{
w[i][i] = q[i];
r[i][i] = 0;
c[i][i] = 0;
w[i][i + 1] = q[i] + q[i + 1] + p[i + 1];
r[i][i + 1] = i + 1;
c[i][i + 1] = q[i] + q[i + 1] + p[i + 1];
printf("%d %d\t%d\t%d\t%d\n", i, i, w[i][i], c[i][i], r[i]
[i]);
}
w[n][n] = q[n];
r[n][n] = 0;
c[n][n] = 0;
printf("%d %d\t%d\t%d\t%d\n", n, n, w[n][n], c[n][n], r[n][n]);
for (int k = 1; k <= n; k++)
{
for (int i = 0, j = k; j <= n; i++, j++) // Since table is
of upper left triangular format
{
if (i != j && j - i != 1)
{
w[i][j] = p[j] + q[j] + w[i][j - 1];
min = __INT32_MAX__;
for (int l = i + 1; l <= j; l++)
{
min1 = c[i][l - 1] + c[l][j];
if (min1 < min)
{
min = min1;
temp = l;
}
}
c[i][j] = min + w[i][j];
r[i][j] = temp;
}
printf("%d %d\t%d\t%d\t%d\n", i, j, w[i][j], c[i][j],
r[i][j]);
}
}
printf("The minimum cost is %d.\n", c[0][n]);
printf("The level order traversal is:\n");
printf("Root = %d = %s.\n", r[0][n], iden[r[0][n]]);
levelorder(r, 0, n, n);
}
int main()
{
int w[MAX][MAX], c[MAX][MAX], r[MAX][MAX];
int n;
int i, j, k, b;
printf("Enter the number of elements: \n");
scanf("%d", &n);

Roll No. 211105036 |Page


printf("Enter %d identifiers.\n", n);
for (i = 1; i <= n; i++)
scanf("%s", iden[i]);
printf("Enter %d success probabilities.\n", n);
for (i = 1; i <= n; i++)
scanf("%d", &p[i]);
printf("Enter %d failure probabilities.\n", n + 1);
for (i = 0; i <= n; i++)
scanf("%d", &q[i]);
OBST(w, c, r, n);
printf("\n");
return 0;
}

OUTPUT :

PS D:\SE SEM IV\MADF LAB> gcc obst.c


PS D:\SE SEM IV\MADF LAB> ./a.exe
Enter the number of elements:
5
Enter 5 identifiers.
Apr Mar May Oct Sept
Enter 5 success probabilities.
34324
Enter 6 failure probabilities.
445454
00 4 0 0
11 4 0 0
22 5 0 0
33 4 0 0
44 5 0 0
55 4 0 0
0 1 11 11 1
1 2 13 13 2
2 3 12 12 3
3 4 11 11 4
4 5 13 13 5
0 2 20 31 2
1 3 20 32 2
2 4 19 30 3
3 5 19 30 5
0 3 27 50 2
1 4 27 51 3
2 5 27 52 4
0 4 34 75 2
1 5 35 78 3
0 5 42 103 3
The minimum cost is 103.
The level order traversal is:
Root = 3 = May.
2 = Mar 5 = Sept
1 = Apr 4 = Oct

Roll No. 211105036 |Page


PS D:\SE SEM IV\MADF LAB>

e) 0/1 KNAPSACK PROBLEM


Date:11/04/2023
Problem Statement:
Write a c program to implement 0/1 knapsack using dynamic programming on the following knapsack :

N=7

M=15

p1,p2,p3,p4,p5,p6,p7={3,2,3,4,5,2,3}

w1,w2,w3,w4,w5,w6,w7={15,14,16,21,17,14,13}

Algorithm

Roll No. 211105036 |Page


Time and space complexity :

Time complexity ;
The time complexity of solving the 0/1 knapsack problem using dynamic programming is
typically O(nW), where n is the number of items and W is the maximum weight or capacity
of the knapsack.
In the dynamic programming approach, we create a table or matrix to store the maximum
value achievable for different combinations of items and knapsack capacities. The table has
dimensions (n+1) x (W+1), representing the number of items and the range of knapsack
capacities.
We iterate over each item and consider two possibilities: including the item in the knapsack
or excluding it. For each item and knapsack capacity, we calculate the maximum value based
on these two possibilities and the values and weights of the items.

Roll No. 211105036 |Page


Since we need to consider each item for each knapsack capacity, the outer loop runs n times,
and the inner loop runs W times. Hence, the time complexity of the dynamic programming
approach for the 0/1 knapsack problem is O(nW).
It's important to note that the time complexity can be further improved by using
optimizations such as memoization or applying heuristics. However, the basic dynamic
programming approach has a time complexity of O(nW).

Space complexity :
The space complexity of solving the 0/1 knapsack problem using dynamic programming is
typically O(nW), where n is the number of items and W is the maximum weight or capacity
of the knapsack.
In the dynamic programming approach, we create a table or matrix to store the maximum
value achievable for different combinations of items and knapsack capacities. The table has
dimensions (n+1) x (W+1), representing the number of items and the range of knapsack
capacities.
To calculate the maximum value for each combination of items and capacities, we only need
to store the values of the current row and the previous row of the table. We can update the
table row by row, using the information from the previous row to compute the current row.
Therefore, the space required for storing the table is O(nW), as we need to maintain the
values for each combination of items and knapsack capacities.
It's worth noting that there are space optimization techniques that can reduce the space
complexity to O(W). These techniques exploit the fact that we only need to store the
information for the current row and the previous row of the table at any given time.
Overall, the space complexity of the 0/1 knapsack problem using dynamic programming is
typically O(nW), where n is the number of items and W is the maximum weight or capacity
of the knapsack.

Code
#include <stdio.h>
#include <limits.h>
#define N 200
#define obj 100
int count = 0;

int size;

struct dp
{
int p, w, o[obj];

};

void get(int a[N], int n)


{
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
}

void purge(struct dp s[N])

{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)

Roll No. 211105036 |Page


{
if (s[i].p < s[j].p && s[i].w >= s[j].w)
s[i].p = s[i].w = -1;
else if (s[j].p < s[i].p && s[j].w >= s[i].w)
s[j].p = s[j].w = -1;
}
for (int j = i + 1; j < size; j++)
{
if (s[i].p == s[j].p && s[i].w == s[j].w)
s[j].p = s[j].w = -1;
}
}
}

void knap(int m, int n, int p[N], int w[N])


{
struct dp s[N];
s[0].w = s[0].p = 0;
for (int i = 0; i < n; i++)
s[0].o[i] = 0;

size = 1;

for (int i = 0; i < n; i++)


{
for (int j = 0, k = size; j < size; j++, k++)
{
if (s[j].w == -1)
continue;

s[k].w = s[j].w + w[i];

if (s[k].w > m)
{
s[k].w = s[k].p = -1;
continue;
}

s[k].p = s[j].p + p[i];

for (int z = 0; z < n; z++)


s[k].o[z] = s[j].o[z];
s[k].o[i] += 1;
}
purge(s);
printf("S^%d = { ", count);
for (int i = 0; i < size; i++)
{
if (s[i].p == -1 && s[i].w == -1)
continue;
else
printf("(%d, %d) ", s[i].p, s[i].w);
}
printf("}");
printf("\n\n");
size *= 2, count++;
}
purge(s);
int maxw = -1, maxp = -1, ind;
for (int i = 0; i <= size; i++)
{
if (s[i].w < maxw)
continue;
else if (s[i].w > maxw)
maxw = s[i].w, maxp = s[i].p, ind = i;
else
{
if (s[i].p > maxp)

Roll No. 211105036 |Page


maxp = s[i].p, ind = i;
}
}
printf("Max Profit: %d\nKnapsack filled at: %d\nObjects: ( ",
maxp, maxw);
for (int i = 0; i < n; i++)
{
if (s[ind].o[i] != 1)
printf("0 ");
else
printf("%d ", s[ind].o[i]);
}
printf(")\n");
}

int main(int argc, char const *argv[])


{
int m, n;
printf("Enter the knapsack capacity: ");
scanf("%d", &m);
printf("Enter the number of elements: ");
scanf("%d", &n);
int p[n], w[n];
printf("Enter the profit for each item\n");
get(p, n);
printf("Enter the weights for each item\n");
get(w, n);
knap(m, n, p, w);
return 0;
}

OUTPUT :
PS D:\SE SEM IV\MADF LAB> gcc knap.c
PS D:\SE SEM IV\MADF LAB> ./a.exe
Enter the knapsack capacity: 6
Enter the number of elements: 3
Enter the profit for each item
1
2
5
Enter the weights for each item
2
3
4
S^0 = { (0, 0) }

S^1 = { (0, 0) (1, 2) }

S^2 = { (0, 0) (1, 2) (2, 3) (3, 5) }

S^3 = { (0, 0) (1, 2) (2, 3) (5,4) (6,6)}

Max Profit: 6
Knapsack filled at: 6
Objects: ( 1 0 1 )

CONCLUSION:

Roll No. 211105036 |Page


The Dynamic Programming Method was studied.
The programs for:
(a) Multistage Graph
(b) All Pair Shortest Path
(c) Bellman Ford Algorithm
(d) Optimal binary search tree
(e) 0/1 knapsack problem
were studied and implemented successfully.

Roll No. 211105036 |Page


Roll No. 211105036 |Page

You might also like