Data Structures and Algorithms Unit - V: Dynamic Programming
Data Structures and Algorithms Unit - V: Dynamic Programming
UNIT – V
DYNAMIC PROGRAMMING
We have already discussed what a Knapsack problem is. Now let us see how to solve
this using dynamic programming.
Given:
• n Number of objects
• m Total capacity of the sack
• w[ ] weights of the objects
• p[ ] profits of the objects
• Fill the sack up to maximum capacity such that the total profit of selected
objects is maximized.
i =n
∑x
i =1
i p i is maximized
Constraint:
• Total weight of the selected objects should not exceed the maximum
capacity of the sack.
i =n
∑x w
i =1
i i ≤m
Example:
N = 3, M = 6
W = { 2, 3, 4 }
P = { 1, 2, 5 }
The Knapsack problem using dynamic programming is solved by first generating all the
feasible solutions and then selecting the optimum solution.
Si+1 = Si + Si1
Initially no objects are selected and hence the set has only pair (0,0) in the set.
The set S01 is generated by adding (P,W) = (1,2) of the selected object with every pair of
the set S0. Similarly the consecutive sets are generated as follows.
Now in the last set S3 gives all the possible feasible solutions. From this the solution with
the best value is (6,6) and hence this is the optimal solution.
The objects selected corresponding to the solution (6,6) is found out using the following
technique.
• First find whether (6,6) is present in the previous set S 2. If it is not present then
the third object is selected. The solution of this intermediate stage is (6,6) – (5,4)
= (1,2).
• Now find out whether (1,2) is present in the previous set S1. We find that this is
not present and hence the second object cannot be selected.
• Now find out whether (1,2) is present in the previous set S0. We find that this is
present in that set. Therefore the first object is selected.
• Therefore the final solution is
X={1 0 1}
Algorithm
for i = 1 to n
for j = 1 to s[i-1].c
s[i].p[j] = s[i-1].p[j] + p[i]
s[i].w[j] = s[i-1].w[j] + w[i]
s[i].c = s[i].c + 1
Given:
• A graph showing n number of cities connected by edges.
• Cost of each edge is given using the cost matrix.
Find the shortest path to cover all the cities and come back to the same city.
Constraints:
Solution:
Example:
Consider the following example. There are 4 cities given. These are connected with
edges as shown. The cost of the edges are shown.
1 2 3 4
1 0 20 5 10
2 20 0 15 25
3 5 15 0 5
4 10 25 5 0
Let us start visiting from the node 1. Then the remaining 3 cites are 2, 3 and 4. By
applying the permutation function we generate the following possible paths.
1 2 3 4 1 50
1 2 4 3 1 55
1 3 2 4 1 55
1 3 4 2 1 55
1 4 2 3 1 55
1 4 3 2 1 50
Now calculate the cost of each path and select the minimum of these. If there more than
one path having the same cost, then first occurring path is selected.
As per the results shown above, the shortest path selected is the first path.
Algorithm
TRAVEL(cost[ ], n )
x=2
for s = 1 to n – 1
list[s] = x
x=x+1
end for
for i = 1 to (n – 1)!
for j = 2 to n
path[i][j] = perm(list)
path[i][j] = path[i][n] = 1
pathcost[i] = 0
end for
end for
for i = 1 to (n-1)!
for j = 1 to n
pathcost[i] = pathcost[i] + cost[path[i][j]][path[i][j+1]]
end for
end for
min = 0, minpos = 0
for i = 1 to (n-1)!
If pathcost[i] < min
min = pathcost[i]
minpos =i
end if
end for
end Travel
Program
#include <iostream.h>
#include <conio.h>
dynamic::dynamic()
{
r=0;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
c[i][j]=0;
}
void dynamic::getdata()
{
cout<<"Enter no. of cities:";
cin>>n;
cout<<endl;
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
{
if (i!=j)
{
if (c[i][j]==0)
{
cout<<"Enter cost from "<<i<<" to "<<j<<" :";
cin>>c[i][j];
c[j][i]=c[i][j];
}
}
}
}
for (i=0;i<n-1;i++)
list[i]=i+1;
}
void dynamic::sol()
{
perm(list,0,n-2);
for (int i=0;i<fact(n-1);i++)
{
p[i][0]=0;
p[i][n]=0;
}
for (i=0;i<fact(n-1);i++)
{
d[i]=0;
for (int j=0;j<n;j++)
{
d[i]=d[i]+c[p[i][j]][p[i][j+1]];
}
}
}
void dynamic::display()
{
int i,j;
cout<<endl<<"The cost Matrix:"<<endl;
for (i=0;i<n;i++)
{
for (j=0;j<n;j++)
cout<<c[i][j]<<"\t";
cout<<endl;
}
cout<<endl<<"The Possible paths and their corresponding cost:"<<endl;
for (i=0;i<fact(n-1);i++)
{
for (j=0;j<n+1;j++)
cout<<p[i][j]<<"\t";
cout<<"--> "<<d[i]<<endl;
}
cout<<endl<<"The shortest path :"<<endl;
for (i=0;i<fact(n-1);i++)
{
if (d[i]==min(d))
break;
}
for (j=0;j<=n;j++)
{
cout<<p[i][j]<<" ";
}
cout<<endl<<"\nThe cost of this path is "<<d[i]<<endl;
}
void main()
{
clrscr();
dynamic ts;
ts.getdata();
ts.sol();
ts.display();
getch();
}
Output
BACKTRACKING METHOD
• We begin by defining a solution space for the problem. The solution space is
the collection all possible solutions to the given problem. The solution space
is usually represented as a tree or a graph.
• Organize solution space so that it can be easily searched.
• Once we have defined an organization for the solution space, this is searched
in a depth first manner (DFS).
• During the search if infeasible solution is sensed then backtrack to previous
node.
• The search terminates when we have found the answer.
We have already discussed about the knapsack problem. Let us see how to solve
this using the backtracking method.
In this method a solution space is defined for the knapsack problem as shown.
Given:
• n Number of objects
• m Total capacity of the sack
• w[ ] weights of the objects
• p[ ] profits of the objects
• Fill the sack up to maximum capacity such that the total profit of selected
objects is maximized.
i =n
∑x
i =1
i p i is maximized
Constraint:
• Total weight of the selected objects should not exceed the maximum
capacity of the sack.
i =n
∑x w
i =1
i i ≤m
Example:
N = 3, M = 6
W = { 2, 3, 4 }
P = { 1, 2, 5 }
Solution:
Initially we are in level 0 of the solution space. Select the first object. Since the first
object is selected, we move towards the left child of current node. Now we have moved
to level 1. Compare the weight of the object selected with the available capacity of the
sack.
2<6
Remaining capacity 6 – 2 = 4
Therefore so far the solution is correct. Now select the second object which has a weight
3 and move towards the left child of the current node. Now we have moved to level 2.
Compare the weight of the object selected with the available capacity of the sack.
3<4
Remaining capacity 4 – 3 = 1
Now select the third object which has weight 4 and move towards the left child of the
current node. Now we have moved to level 3. Compare the weight of this object with
the available capacity.
4>1
The weight of the object exceeds the available capacity. This leads to an infeasible
solution. Therefore backtrack to previous node which is in level 2. Move towards the
right child indicating that the third object is not selected.
As we have reached the leaf node with a feasible solution, the algorithm comes to an end.
X = { 1, 1, 0 }
Algorithm
End KNAPSACK
The solution for the 8 queens problem is easily obtained using the backtracking
algorithm.
Given,
Place 8 queens on the chessboard in such a way that none of the queens hit each other.
Constraint:
Solution:
If a queen is placed in position (i, j ). Now a new queen is placed in the position (k, l)
then the two queens are said to be in the same diagonal if following conditions are
satisfied.
i+j=k+l
i–j=k–l
Abs(i – k) = Abs(j – l)
Now queens are placed one by one in the chessboard by checking the above conditions.
If at any stage we are unable to place a queen, then we have to backtrack and change the
position of the previous queen. This is repeated till we place all the 8 queens on the
board.
The algorithm Place checks and tells whether the new position of the queen is correct or
not. If it is correct, then it returns true otherwise it returns false.
Example:
Solution is:
1 5 8 6 3 7 2 4
Algorithm
PLACE( k, L )
NQUEEN( k, n )
For i = 1 to n
If PLACE( k, i ) = TRUE
x[k] = i
if k = n
print x[ ]
else
NQUEEN( k + 1, n )
End if
End if
End for
End NQUEEN
Program
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
class queen
{
private:
int x[9];
public:
int place(int k, int i);
void eightqueen(int k);
};
void queen::eightqueen(int k)
{
void main()
{
clrscr();
queen q;
q.eightqueen(1);
getch();
}
Output
1 5 8 6 3 7 2 4
1 6 8 3 7 4 2 5
1 7 4 6 8 2 5 3
1 7 5 8 2 4 6 3
The branch and bound method is similar to the backtracking method except that,
this method searches the nodes of the solution space in the Breadth First Search method.
This braches to various nodes in search of the solution, but if an infeasible solution is
encountered, then we bound back and try the next adjacent branch.
We have already solved this problem using the dynamic programming method.
Now let us see how to solve this problem using branch and bound technique.
Given:
• A graph showing n number of cities connected by edges.
• Cost of each edge is given using the cost matrix.
Constraints:
Solution:
The given graph is the solution space for this problem. Hence we perform a BFS
in this graph to find the solution.
Start from node 1.
• Find all the adjacent nodes of the current node.
• Select the node which is not yet visited and has a least cost edge.
• Move to the selected node and repeat the above steps.
The solution is obtained when al the nodes are visited and we come back to the same city.
Example:
1 2 3 4
1 0 20 5 10
2 20 0 15 25
3 5 15 0 5
4 10 25 5 0
In the given graph, we start from node 1. The adjacent nodes of 1 are 2, 3, and 4. But we
select node 3 as it has the minimum cost edge. Move to node 3. Repeat the process till
we reach the node 1.
Algorithm
BBTRAVEL( cost[ ], n )
u = city 1
Repeat while(all cities visited)
Find all cities w adjacent from u
If (cost of edge is minimum ) and (city not yet visited)
Move to that city and mark it visited
u = current city
End if
End Repeat
Calculate path cost
Print Shortest path and its cost
End TRAVEL
We have already solved this problem using Greedy approach. Now let us use
branch and bound technique to solve this problem. In this problem, there is a ship with
capacity m. The number of containers n is given and their respective weights are also
given. The containers should be loaded in such a way that we load maximum number of
containers in the ship and the total weight of the containers loaded into the ship does not
exceed the capacity of the ship.
Given:
n = Number of containers
w[ ] = Weights of the containers
m = Total capacity of the ship
∑x
i =1
i is maximized.
Constraints:
The total weight of the containers loaded should not exceed the capacity of the
ship.
∑x w
i =1
i i ≤m
Solution:
• Develop a solution space, which is represented as tree with left child indicating
that the container is selected and the right child indicating that the container is not
selected.
• Initially we are in the root node. We branch towards the left child and check
whether the container weight is lesser than or equal to the available capacity. If
not, that is a infeasible solution and hence we bound back and select the next
adjacent branch. But if the solution is feasible at that stage, we continue selecting
the next container.
Example:
w = { 20, 40, 50 }
Start from the root node. Select the first container by moving to the left child. Compare
the weight of the first container with the remaining capacity of the ship.
20 < 70
Remaining capacity = 70 – 20 = 50
Now select the second container by branching towards the left child. Compare the
weight of the container with the available capacity of the ship.
40 < 50
Remaining capacity = 10
Now select the third container by branching towards the left child. Compare the weight
of the container with the available capacity of the ship
50 > 10
As the capacity of the container exceeds the capacity of the ship, bound back and go to
adjacent branch. As the leaf node is reached and the solution is a feasible solution, the
algorithm stops here.