DAA Lab Manual
DAA Lab Manual
(2022-2023)
COURSE TITLE: DESIGN AND ANALYSIS OF ALGORITHMS LAB
SEMESTER: IV
LAB OBJECTIVES:
Algorithm Design:
The important aspects of algorithm design include creating an efficient algorithm
to solve a problem in an efficient way using minimum time and space. To solve a
problem, different approaches can be followed. Some of them can be efficient
with respect to time consumption, whereas other approaches may be memory
efficient. However, one has to keep in mind that both time consumption and
memory usage cannot be optimized simultaneously.
The Need for Analysis: Algorithms are often quite different from one another,
though the objectives of these algorithms are the same. Analysis of algorithm is the
process of analyzing the problem-solving capability of the algorithm in terms of
the time and size required. Generally, the following types of analysis are
performed −
Worst-case − the maximum number of steps taken on any instance of size a.
Best-case − the minimum number of steps taken on any instance of size a.
Average case − the average number of steps taken on any instance of size a.
SNO PROGRAM
Sort a given set of elements using the Quick sort method and determine the
time required to sort the elements. Repeat the experiment for different values
1. of n, the number of elements in the list to be sorted. The elements can be
read from a file or can be generated using the random number generator.
Implement a Merge Sort algorithm to sort a given set of elements and
determine the time required to sort the elements. Repeat the experiment for
2. different values of n, the number of elements in the list to be sorted .The
elements can be read from a file or can be generated using the random
number generator.
A) Obtain the Topological ordering of vertices in a given digraph.
3. B) Compute the transitive closure of a given directed graph using Warshall's
algorithm.
4. Implement 0/1 Knapsack problem using Dynamic Programming.
From a given vertex in a weighted connected graph, find shortest paths to
5. other vertices using Dijikstra’s algorithm
Find Minimum Cost Spanning Tree of a given undirected graph using
6. Kruskal’s algorithm.
A) Print all the nodes reachable from a given starting node in a digraph using
7. BFS method.
B) Check whether a given graph is connected or not using DFS method.
Find a subset of a given set S = {s1, s2,….., sN} of n positive integers whose
sum is equal to a given positive integer d. For example, if S= {1, 2, 5, 6, 8}
8. and d = 9 there are two solutions {1,2,6}and{1,8}.A suitable message is to
be displayed if the given problem instance doesn't have a solution.
Implement any scheme to find the optimal solution for the Traveling
9. Salesperson problem and then solve the same problem instance using any
approximation algorithm and determine the error in the approximation.
Find Minimum Cost Spanning Tree of a given undirected graph using Prim’s
10. algorithm.
11. Implement All-Pairs Shortest Paths Problem using Floyd's algorithm.
12. Implement N Queen's problem using Back Tracking.
Program Number 1:
Sort a given set of elements using the Quick sort method and determine the
time required to sort the elements. Repeat the experiment for different values
of n, the number of elements in the list to be sorted and plot a graph of the
time taken versus n. The elements can be read from a file or can be
generated using the random number generator.
Quick Sort is a Divide and Conquer algorithm. It picks an element as pivot and
partitions the given array around the picked pivot. There are many different
versions of quick Sort that pick pivot in different ways.
Always pick first element as pivot.
Always pick last element as pivot (implemented below)
Pick a random element as pivot.
Pick median as pivot.
The key process in quick Sort is partition (). Target of partition() is, given an array
and an element x of array as pivot, put x at its correct position in sorted array and
put all smaller elements (smaller than x) before x, and put all greater elements
(greater than x) after x.
1 Algorithm Partition(a,m,p)
2 // Within a[m],a[m+1],... ,a[p-1]the elements are
3 // rearranged in such a manner that if initially t = a[m],
4 // then after completion a[q] = t for some q between m
5 // and p-1,a[k] ≤ t for m ≤ k < g, and a[k] ≥ t
6 // for q <k <p. q is returned. Set a[p] = ∞.
7{
8 v:=a[m]; i:=m; j :=p;
9 repeat
10 {
11 repeat
12 i:=i+1;
13 until(a[i] > v);
14 repeat
15 j: =j-1;
16 until (a[j] <v);
17 if (i <j) then lnterchange(a,i,j);
18 } until(i >= j);
19 a[m] :=a[j]; a[j] :=v; return j;
20}
1 Algorithm Interchange (a,i,j)
2 // Exchange a[i] with a[j].
3{
4 p: =a[i];
5 a[i]:=a[j]; a[j]:=p;
6
1 Algorithm QuickSort(p, q)
2 // Sorts the elements a[p],..., a[q] which reside in the global
3 // array a[l:n] into ascending order; a[n+1]is considered to
4 //be defined and must be >= all the elements in a[l:n].
5{
6 if (p <q) then //If there are more than one element
7 {
8 // divide P into two sub problems.
9 j :=Partition(a,p, q + 1);
10 // j is the position of the partitioning element.
11 // Solve the sub problems.
12 QuickSort(p,j-1);
13 QuickSort(j+ l,q);
14 // There is no need for combining solutions.
15 }
16}
Complexity:
Merge Sort is a Divide and Conquer algorithm. It divides the input array into two
halves, calls itself for the two halves, and then merges the two sorted halves. The
Merge() function is used for merging two halves. The Mergesort() is a key process
that sorts the A[l..m] and A[m+1..r] into two sorted sub-arrays.
1 Algorithm MergeSort(low,high)
2 // a[low :high]is a global array to be sorted.
3 // Small(P)is true if there is only one element
4 // to sort. In this case the list is already sorted.
5{
6 if (low <high) then //If there are more than one element
7 {
8 // Divide P into sub problems.
9 // Find where to split the set.
10 mid:=[(low+high)/2];
11 // Solve the sub problems.
12 MergeSort(low, mid);
13 MergeSort(mid+1 ,high);
14 // Combine the solutions.
15 Merge(low,mid,high);16
}
17}
1 Algorithm Merge(low,mid,high)
2 //a[low:high] is a global array containing two sorted
3//subsets in a[low:mid] and in a[mid+1:high].The goal
4//is to merge these two sets into a single set residing
5//in a[low :high]. b[ ]is an auxiliary global array.
6{
7 h :=low; i :=low; j :=mid+ 1;
8 while ((h <=mid) and (j <= high)) do
9 {
10 if (a[h] <=a[j]) then
11 {
12 b[i]:=a[h]; h :=h + 1;
13 }
14 else
15 {
16 b[i] =a[j]; j :=j + l;
17 }
18 i :=i +1;
19 }
20 if (h >mid) then
21 for k :=j to high do
22 {
23 b[i] :=a[k]; i :=i +1;
24 }
25 else
26 for k :=h to mid do
27 {
28 b[i] :=a[k]; i :=i +1;
29 }
30 for k:=low to high do a[k] :=b[k];
31}
Complexity:
1Algorithm Topological(a[],n,T[])
2// obtains the sequence of jobs to be executed resulting in topological order
3// a[]-adjacency matrix of the given graph
4// n-the number of vertices in the graph
5//T[]-indicates the jobs that are to be executed in the order
6{
7 for j:=0 to n-1 do
8 {
9 sum:=0;
10 for i:=0 to n-1 do
11 sum:=sum+a[i][j];12 top
:=-1;
13 for i:= 0 to n-1 do
14 {
15 if(indegree [i]==0) then
16 {
17 top := top+1;
18 s[top]:= i ;
19 }
20 }
21 while(top!=1) do
22 {
23 u:=s[top] ;
24 top:=top-1;
25 Add u to solution vector T For each vertex v adjacent to u, decrement indegree [v] by one
26 if(indegree [v]==0) then
27 {
28 top:=top+1;
29 s[top]:=v;
30 }
31 }
32 return T;
33}
#include<iostream>
using namespace std;
void findindegree(int [10][10],int[10],int);
void topological(int,int [10][10]);
int main()
{
int a[10][10],i,j,n;
cout<<"Enter the number of nodes:";
cin>>n;
cout<<"\nEnter the adjacency matrix\n";
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
cin>>a[i][j];
cout<<"\nThe adjacency matirx is:\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cout<<a[i][j]<<"\t";
}
cout<<"\n";
}
topological(n,a);
}
void findindegree(int a[10][10],int indegree[10],int n)
{
int i,j,sum;
for(j=1;j<=n;j++)
{
sum=0;
for(i=1;i<=n;i++)
{
sum=sum+a[i][j];
}
indegree[j]=sum;
}
}
void topological(int n,int a[10][10])
{
int k,top,t[100],i,stack[20],u,v,indegree[20];
k=1;
top=-1;
findindegree(a,indegree,n);
for(i=1;i<=n;i++)
{
if(indegree[i]==0)
{
stack[++top]=i;
}
}
while(top!=-1)
{
u=stack[top--];
t[k++]=u;
for(v=1;v<=n;v++)
{
if(a[u][v]==1)
{
indegree[v]--;
if(indegree[v]==0)
{
stack[++top]=v;
}
}
}
}
cout<<"\nTopological sequence is\n";
for(i=1;i<=n;i++)
cout<<t[i]<<"\t";
}
Program Number 3(b):
Compute the transitive closure of a given directed graph using Warshall's
algorithm.
The transitive closure of a directed graph with n vertices can be defined as the n-
by-n Boolean matrix T={tij}, in which the element in the ith row(1<=i<=n) and jth
column(1<=j<=n) is 1 if there exists a non trivial directed path from ith vertex to jth
vertex, otherwise, tij is 0.Warshall’s algorithm constructs the transitive closure of a
given digraph with n vertices through a series of n-by-n boolean matrices: R(0)
,….,R(k-1) , R(k),….,R(n) where, R(0) is the adjacency matrix of digraph and R(1)
contains the information about paths that use the first vertex as intermediate.
In general, each subsequent matrix in series has one more vertex to use as
intermediate for its path than its predecessor. The last matrix in the series R (n)
reflects paths that can use all n vertices of the digraph as intermediate and finally
transitive closure is obtained. The central point of the algorithm is that we compute
all the elements of each matrix R (k) from its immediate predecessor R (k-1) in series.
Algorithm Warshall(A[1..n,1..n])
//Implements Warshall’s algorithm for computing the transitive closure
//Input: The Adjacency matrix A of a digraph with n vertices
//Output: The transitive closure of digraph
{
R(0):= A
for k :=1 to n do
{
for i := 1 to n do
{
for j := 1 to n do
{
R(k)[i,j] := R(k-1)[i,j] or R(k-1)[i,k] and R(k-1)[k,j]
}
}
}
return R(n)
}
Given n objects and a knapsack or bag. Object i has a weight w i and the knapsack
has a capacity m. If a fraction xi, 0 < 1, of object i is placed into the knapsack, then
a profit of pixi is earned. The objective is to obtain a filling of the knapsack that
maximizes the total profit earned. Since the knapsack capacity is m, the total
required is the weight of all chosen objects to be at most m.
1Algorithm 0/1DKnapsack(v,w,n,W)
2//Input: set of items with weight wi and value vi; maximum capacity of knapsack W
3//Output: maximum value of subset with weight at most W.
6{
7 for w := 0 to W do
8 V[0,w] :=0;
9 for i :=1 to n do
10 for w:=0 to W do
11 if (w[i]<=w)
12 V[i,w]=max{V[i-1,w],v[i]+V[i-1,w-w[i]]};
13 else
14 V[i,w]=V[i-1,w];
15 return V[n,W];
16 }
Complexity: The Time efficiency and Space efficiency of 0/1 Knapsack algorithm
is Ө(nW).
PROGRAM:
#include<iostream>
#define MAX 50
int p[MAX],w[MAX],n;
int knapsack(int,int);
int max(int,int);
using namespace std;
int main()
{
int m,i,optsoln;
cout<<"Enter no. of objects: ";
cin>>n;
cout<<"\nEnter the weights:\n";
for(i=1;i<=n;i++)
cin>>w[i];
cout<<"\nEnter the profits:\n";
for(i=1;i<=n;i++)
cin>>p[i];
cout<<"\nEnter the knapsack capacity:";
cin>>m;
optsoln=knapsack(1,m);
cout<<"\nThe optimal soluntion is:"<<optsoln;
}
int knapsack(int i,int m)
{
if(i==n)
return (w[n]>m) ? 0: p[n];
if(w[i]>m)
return knapsack(i+1,m);
return max(knapsack(i+1,m),knapsack(i+1,m-w[i])+p[i]);
}
int max(int a, int b)
{
if(a>b)
return a;
else
return b;
}
Program Number 5:
From a given vertex in a weighted connected graph, find shortest paths
to other vertices using Dijkstra's algorithm.
Single Source Shortest Paths Problem: For a given vertex called the source in a
weighted connected graph, find the shortest paths to all its other vertices. Dijkstra’s
algorithm is the best known algorithm for the single source shortest paths problem.
This algorithm is applicable to graphs with nonnegative weights only and finds the
shortest paths to a graph’s vertices in order of their distance from a given source. It
finds the shortest path from the source to a vertex nearest to it, then to a second
nearest, and so on. It is applicable to both undirected and directed graphs.
1 Algorithm ShortestPaths(u,cost,dist,n)
2 // dist[j], 1<j <n, is set to the length of the shortest
3 // path from vertex v to vertex j in a digraph G with n
4 // vertices. dist[v] is set to zero. G is represented by its
5 // cost adjacency matrix cost [l : n, 1 : n].
6{
7 for i: =1to n do
8 {// Initialize S.
9 S[i]:=false; dist[i]:=cost [v,i];10 }
11 S[v]:=true; dist[v]:=0.0; // Put v in S.
12 for num: =2 to n do
13 {
14 // Determine n-1paths from v.
15 Choose u from among those vertices not
16 in S such that dist[u] is minimum;
17 S[u]:=true; // Put u in S.
18 for (each w adjacent to u with S[w] = false) do
19 // Update distances.
20 if {dist[w] > dist[u] + cost [u, w])) then
21 dist[w]:=dist[u] +cost [u, w];22 }
23}
Complexity: The Time complexity for Dijkstra’s algorithm is O (|E| log |V|).
PROGRAM:
#include<iostream>
using namespace std;
void dij(int,int [20][20],int [20],int [20],int);
int main()
{
int i,j,n,visited[20],source,cost[20][20],d[20];
cout<<"Enter no. of vertices:";
cin>>n;
cout<<"Enter the cost adjacency matrix\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>cost[i][j];
}
}
cout<<"\nEnter the source node:";
cin>>source;
dij(source,cost,visited,d,n);
for(i=1;i<=n;i++)
if(i!=source)
cout<<"\nShortest path from"<<source<<"to"<<i<<"is"<<d[i];
}
void dij(int source,int cost[20][20],int visited[20],int d[20],int n)
{
int i,j,min,u,w;
for(i=1;i<=n;i++)
{
visited[i]=0;
d[i]=cost[source][i];
}
visited[source]=1;
d[source]=0;
for(j=2;j<=n;j++)
{
min=999;
for(i=1;i<=n;i++)
{
if(!visited[i])
{
if(d[i]<min)
{
min=d[i];
u=i;
}
}
}
visited[u]=1;
for(w=1;w<=n; w++)
{
if(cost[u][w]!=999 && visited[w]==0)
{
if(d[w]>cost[u][w]+d[u])
d[w]=cost[u][w]+d[u];
}
}
}
}
Program Number 6:
Find Minimum Cost Spanning Tree of a given undirected graph using
Kruskal's algorithm.
Kruskal's algorithm: Kruskal’s algorithm finds the minimum spanning tree for a
weighted connected graph G=(V,E) to get an acyclic sub graph with |V|-1
edges for which the sum of edge weights is the smallest. Consequently the
algorithm constructs the minimum spanning tree as an expanding sequence
of sub graphs, which are always acyclic but are not necessarily connected on the
intermediate stages of algorithm. The algorithm begins by sorting the graph’s
edges in non decreasing order of their weights. Then starting with the empty sub
graph, it scans the sorted list adding the next edge on the list to the current sub
graph if such an inclusion does not create a cycle and simply skipping the edge
otherwise.
#include <iostream>
int ne=1,mincost=0,parent[20];
int find(int);
int uni(int,int);
using namespace std;
int main()
{
int n,i,j,min,cost[20][20],a,b,u,v;
cout<<"\nEnter the no. of vertices:";
cin>>n;
cout<<"\nEnter the cost adjacency matrix:\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>cost[i][j];
if(cost[i][j]==0)
cost[i][j]=999;
}
}
cout<<"The edges of Minimum Cost Spanning Tree are\n";
while(ne < n)
{
min=999;
for(i=1;i<=n;i++)
{
for(j=1;j <= n;j++)
{
if(cost[i][j] < min)
{
min=cost[i][j];
a=u=i;
b=v=j;
}
}
}
u=find(u);
v=find(v);
if(uni(u,v))
{
cout<<ne++<<"edge ("<<a<<","<<b<<") ="<<min<<"\n";
mincost +=min;
}
cost[a][b]=cost[b][a]=999;
}
cout<<"\n\t Minimum cost ="<<mincost<<"\n";
}
int find(int i)
{
while(parent[i])
parent[i];
return i;
}
int uni(int i,int j)
{
if(i!=j)
{
parent[j]=i;
return 1;
}
return 0;
}
Breadth First Search: In breadth first search start at a vertex v and mark it as
having been reached (visited). The vertex v is at this time said to be unexplored. A
vertex is said to have been explored by an algorithm when the algorithm has
visited all vertices adjacent from it. All unvisited vertices adjacent from v are
visited next. These are new unexplored vertices. Vertex v has now been explored.
The newly visited vertices haven't been explored and are put onto the end of a list
of unexplored vertices. The first vertex on this list is the next to be explored.
Exploration continues until no unexplored vertex is left. The list of unexplored
vertices operates as a queue and can be represented using any of the standard
queue representation. BFS explores graph moving across to all the neighbors of
last visited vertex traversals i.e., it proceeds in a concentric manner by visiting all
the vertices that are adjacent to a starting vertex, then all unvisited vertices two
edges apart from it and so on, until all the vertices in the same connected
component as the starting vertex are visited. Instead of a stack, BFS uses queue.
1 Algorithm BFS(v)
2 //A breadth first search of G is carried out beginning
3 // at vertex v. For any node i, visited[i] = 1 if i has
4 // already been visited. The graph G and array visited [ ]
5 // are global; visited [ ] is initialized to zero.
6{
7 u: =v; // q is a queue of unexplored vertices.
8 visited[v]:=1;
9 repeat
10 {
11 for all vertices w adjacent from u do
12 {
13 if (visited[w] = 0) then
14 {
15 Add w to q; // w is unexplored.
16 visited[w]:= 1;
17 }
18 }
19 if q is empty then return; // No unexplored vertex.
20 Delete the nest element, u, from q;
21 // Get first unexplored vertex.
22 } until (false);
23}
Complexity: BFS has the time complexity as Θ (V2) for Adjacency matrix
representation and Θ (V+E) for Adjacency linked list representation, where V
stands for vertices and E stands for edges.
PROGRAM:
#include<iostream>
using namespace std;
void BFS(int [20][20],int,int [20],int);
int main()
{
int n,a[20][20],i,j,visited[20],source;
cout<<"Enter the number of vertices:";
cin>>n;
cout<<"\nEnter the adjacency matrix:\n";
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
cin>>a[i][j];
for(i=1;i<=n;i++)
visited[i]=0;
cout<<"\nEnter the source node:";
cin>>source;
visited[source]=1;
BFS(a,source,visited,n);
for(i=1;i<=n;i++)
{
if(visited[i]!=0)
cout<<"\n Node "<<i<<" is reachable";
else
cout<<"\n Node "<<i<<" is not reachable";
}
}
void BFS(int a[20][20],int source,int visited[20],int n)
{
int queue[20],f,r,u,v;
f=0;
r=-1;
queue[++r]=source;
while(f<=r)
{
u=queue[f++];
for(v=1;v<=n;v++)
{
if(a[u][v]==1 && visited[v]==0)
{
queue[++r]=v;
visited[v]=1;
}
}
}
}
Depth First Search: A depth first search of a graph differs from a breadth first
search in that the exploration of a vertex v is suspended as soon as a new vertex is
reached. At this time the exploration of the new vertex u begins. When this new
vertex has been explored, the exploration of v continues. The search terminates
when all reached vertices have been fully explored.
Depth-first search starts visiting vertices of a graph at an arbitrary vertex by
marking it as having been visited. On each iteration, the algorithm proceeds to an
unvisited vertex that is adjacent to the one it is currently in. This process continues
until a vertex with no adjacent unvisited vertices is encountered. At a dead end, the
algorithm backs up one edge to the vertex it came from and tries to continue
visiting unvisited vertices from there. The algorithm eventually halts after backing
up to the starting vertex, with the latter being a dead end.
1 Algorithm DFS(v)
2 // Given an undirected (directed) graph G = (V, E) with
3 // n vertices and an array visited [ ] initially set
4 //to zero, this algorithm visits all vertices
5 // reachable from v. G and visited [] are global.
6{
7 visited[v]:=1;
8 for each vertex w adjacent from v do
9 {
10 if (visited[w] = 0) then DFS (w);
11 }
12}
PROGRAM:
#include<iostream>
using namespace std;
void DFS(int [20][20],int,int [20],int);
int main()
{
int n,a[20][20],i,j,visited[20],source;
cout<<"Enter the number of vertices: ";
cin>>n;
cout<<"\nEnter the adjacency matrix:\n";
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
cin>>a[i][j];
for(i=1;i<=n;i++)
visited[i]=0;
cout<<"\nEnter the source node: ";
cin>>source;
DFS(a,source,visited,n);
for(i=1;i<=n;i++)
{
if(visited[i]==0)
{
cout<<"\nGraph is not connected";
exit(0);
}
}
cout<<"\nGraph is connectd\n";
}
void DFS(int a[20][20],int u,int visited[20],int n)
{
int v;
visited[u]=1;
for(v=1;v<=n;v++)
{
if(a[u][v]==1 && visited[v]==0)
DFS(a,v,visited,n);
}
}
Program Number 8:
Find a subset of a given set S = {sl,s2,.....,sn} of n positive integers whose
sum is equal to a given positive integer d.A suitable message is to be
displayed if the given problem instance doesn't have a solution.
Sum of Subsets: Given n distinct positive numbers, desired to find all combinations
of these numbers whose sums are m. this is called the sum of subsets problem.Sum
of Subset Problem is to find a subset of a given set S= {s 1, s2… sn} of n positive
integers whose sum is equal to a given positive integer d. It is assumed that the
set’s elements are sorted in increasing order. The state-space tree can then be
constructed as a binary tree and applying backtracking algorithm, the solutions
could be obtained. Some instances of the problem may have no solutions.
For example , for s={1,2,5,6,8} and d=9, there are two solutions : {1,2,6} and
{1,8}.
1 Algorithm SumOfSub(s,k,r)
2 // Find all subsets of w [l: n] that sum to m. The values of x[j],
3 // 1<=j <k, have already been determined, s= ∑𝑗=1 𝑘−1 𝑤[𝑗] ∗ 𝑥[𝑗]
6{
7 // Generate left child. Note: s+w[k] <= m since Bk-1 is true.
8 x[k]:=1;
9 if (s+w[k] = m) then write (x[1 : k]); // Subset found
10 // There is no recursive call here as w[j] > 0, 1<=j <=n.
11 else if (s+w[k] +w [k+1]<=m)
12 then SumOfSub (s+w[k], k+1, r-w[k]);
13 // Generate right child and evaluate Bk.
14 if ((s + r- w[k] > = m) and (s + w [k + 1] <= m)) then
15 {
16 x[k]:=0;
17 SumOfSub (s, k+l , r-w[k]);
18 }
19}
Complexity: Subset sum problem solved using backtracking generates at each step
maximal two new sub trees, and the running time of the bounding functions is
linear, so the running time is O (2n).
PROGRAM:
#include<iostream>
using namespace std;
void subset(int,int,int);
int x[10],w[10],d,count=0;
int main()
{
int i,n,sum=0;
cout<<"Enter the no. of elements:";
cin>>n;
cout<<"\nEnter the elements in ascending order:\n";
for(i=0;i<n;i++)
cin>>w[i];
cout<<"\nEnter the sum:";
cin>>d;
for(i=0;i<n;i++)
sum=sum+w[i];
if(sum<d)
{
cout<<"No solution\n";
}
subset(0,0,sum);
if(count==0)
{
cout<<"No solution\n";
}
}
void subset(int cs,int k,int r)
{
int i;
x[k]=1;
if(cs+w[k]==d)
{
cout<<"\n\nSubset"<<++count<<"\n";
for(i=0;i<=k;i++)
if(x[i]==1)
cout<<w[i]<<"\t";
}
else
if(cs+w[k]+w[k+1]<=d)
subset(cs+w[k],k+1,r-w[k]);
if(cs+r-w[k]>=d && cs+w[k]<=d)
{
x[k]=0;
subset(cs,k+1,r-w[k]);
}
}
Program Number 9:
Implement any scheme to find the optimal solution for the Traveling
Salesperson problem and then solve the same problem instance using any
approximation algorithm and determine the error in the approximation.
Traveling Salesperson problem: Given n cities, a salesperson starts at a specified
city (source), visit all n-1 cities only once and return to the city from where he has
started. The objective of this problem is to find a route through the cities that
minimizes the cost and thereby maximizing the profit. Let G = (V, E) be a directed
graph with edge costs cij. The variable cij is defined such that Cij > 0 for all i and j
and Cij = ∞ if <i,j> does not belong to E. Let |V| = n and assume n > 1. A tour of G
is a directed simple cycle that includes every vertex in V. The cost of a tour is the
sum of the cost of the edges on the tour. The traveling salesperson problem is to
find a tour of minimum cost.
To solve the TSP using the Brute-Force approach, you must calculate the total
number of routes and then draw and list all the possible routes. Calculate the
distance of each route and then choose the shortest one—this is the optimal
solution. This method breaks a problem to be solved into several sub-problems.
PROGRAM:
#include<iostream>
using namespace std;
int s,c[100][100],ver;
float optimum=999,sum;
void swap(int v[], int i, int j)
{
int t;
t = v[i];
v[i] = v[j];
v[j] = t;
}
void brute_force(int v[], int n, int i)
{
int j,sum1,k;
if (i == n)
{
if(v[0]==s)
{
for (j=0; j<n; j++)
cout<<v[j]<<"\t";
sum1=0;
for( k=0;k<n-1;k++)
{
sum1=sum1+c[v[k]][v[k+1]];
}
sum1=sum1+c[v[n-1]][s];
cout<<" sum= "<<sum1<<"\n";
if (sum1<optimum)
optimum=sum1;
}
}
else
for (j=i; j<n; j++)
{
swap (v, i, j);
brute_force (v, n, i+1);
swap (v, i, j);
}
}
void nearest_neighbour(int ver)
{
int min,p,i,j,vis[20],from;
for(i=1;i<=ver;i++)
vis[i]=0;
vis[s]=1;
from=s;
sum=0;
for(j=1;j<ver;j++)
{
min=999;
for(i=1;i<=ver;i++)
if(vis[i] !=1 &&c[from][i]<min && c[from][i] !=0 )
{
min= c[from][i];
p=i;
}
vis[p]=1;
from=p;
sum=sum+min;
}
sum=sum+c[from][s];
}
int main ()
{
int ver,v[100],i,j;
cout<<"Enter n :";
cin>>ver;
for (i=0; i<ver; i++)
v[i] = i+1;
cout<<"Enter cost matrix\n";
for(i=1;i<=ver;i++)
for(j=1;j<=ver;j++)
cin>>c[i][j];
cout<<"\nEnter source :";
cin>>s;
brute_force (v, ver, 0);
cout<<"\nOptimum solution with brute force technique
is="<<optimum<<"\n";
nearest_neighbour(ver);
cout<<"\nSolution with nearest neighbour technique is="<<sum<<"\n";
cout<<"\nThe approximation val is="<<((sum/optimum)-1)*100<<"%";
}
1Algorithm Prim(E,cost,n,t)
2 // E is the set of edges in G. cost[1: n , 1: n] is the cost
3 // adjacency matrix of an n vertex graph such that cost [i,j] is
4 // either a positive real number or ∞ if no edge (i,j) exists.
5 //A minimum spanning tree is computed and stored as a set of
6 // edges in the array t [l : n-1,1: 2] .(t[i,l],t[i,2]) is an edge in
7 //the minimum-cost spanning tree. The final cost is returned.
8{
9 Let (k,l) be an edge of minimum cost in E;
10 mincost:= cost[k,l];
11 t[1,l]:=k; t[l,2]:=l;
12 for i :=1 to n do // Initialize near.
13 if (cost[i,l] < cost[i,k]) then near[i]:=l;
14 else near[i]:=k;
15 near[k]:=near[l]:=0;
16 for i :=2 to n-1 do
17 {// Find n-2 additional edges for t.
18 Let j be an index such that near[j] ≠ 0 and
19 cost[ j, near[j]] is minimum;
20 t[i,l]:=j; t[i,2]:=near[j];
21 mincost:=mincost+ cost[j, near[j]];
22 near[j]:=0;
23 for k :=1to n do // Update near[].
24 if ((near[k] ≠ 0) and(cost[k,near[k]] > cost[k,j]))
25 then near[k]:=j;
26 }
27 return mincost;
28}
Complexity: The time complexity of Prim’s algorithm will be in O (|E| log |V|).
PROGRAM:
#include<iostream>
using namespace std;
int ne=1,min_cost=0;
int main()
{
int n,i,j,min,cost[20][20],a,u,b,v,source,visited[20];
cout<<"Enter the no. of nodes:";
cin>>n;
cout<<"Enter the cost matrix:\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cin>>cost[i][j];
}
}
for(i=1;i<=n;i++)
visited[i]=0;
cout<<"Enter the root node:";
cin>>source;
visited[source]=1;
cout<<"\nMinimum cost spanning tree is\n";
while(ne<n)
{
min=999;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(cost[i][j]<min)
if(visited[i]==0)
continue;
else
{
min=cost[i][j];
a=u=i;
b=v=j;
}
}
}
if(visited[u]==0||visited[v]==0)
{
cout<<"\nEdge"<<ne++<<"\t("<<a<<"->"<<b<<")="<<min;
min_cost=min_cost+min;
visited[b]=1;
}
cost[a][b]=cost[b][a]=999;
}
cout<<"\nMinimum cost="<<min_cost<<"\n";
}
1Algorithm Floyd(W[1..n,1..n])
2//Implements Floyd’s algorithm for the all-pairs shortest paths problem
3//Input: The weight matrix W of a graph
4//Output: The distance matrix of shortest paths length
5{
6 D: = W;
7 for k:=1 to n do
8 {
9 for i: = 1 to n do
10 {
11 for j ← 1 to n do
12 {
13 D [i,j] ← min ( D[i, j], D[i, k]+D[k, j] )
14 }
15 }
16 }
17 return D
18}
PROGRAM:
#include<iostream>
using namespace std;
void floyd(int[10][10],int);
int min(int,int);
int main()
{
int n,a[10][10],i,j;
cout<<"Enter the no.of nodes :";
cin>>n;
cout<<"\nEnter the cost adjacency matrix\n";
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
cin>>a[i][j];
floyd(a,n);
}
void floyd(int a[10][10],int n)
{
int d[10][10],i,j,k;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
d[i][j]=a[i][j];
}
for(k=1;k<=n;k++)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
}
cout<<"\nThe distance matrix is\n";
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
cout<<d[i][j]<<"\t";
}
cout<<"\n";
}
}
int min (int a,int b)
{
if(a<b)
return a;
else
return b;
}