CS2206 ALGORITHMS LAB Through C++
1. a) Create a CPP class called Student with the following details as variables within it.
(i) Register_number
(ii) Student_name
(iii) Programme_name
(iv) Phone _number
Write a program to create nStudent objects and print the Register_number,
Student_name, Programme_name, and Phone_number of these objects with suitable
headings.
#include <iostream>
#include <vector>
#include <string>
class Student {
private:
int register_number;
std::string student_name;
std::string programme_name;
std::string phone_number;
public:
// Constructor
Student(int reg_num, const std::string& name, const std::string& program, const std::string&
phone)
: register_number(reg_num), student_name(name), programme_name(program),
phone_number(phone) {}
// Function to print student details
void printDetails() const {
std::cout << "Register Number: " << register_number << std::endl;
std::cout << "Student Name: " << student_name << std::endl;
std::cout << "Programme Name: " << programme_name << std::endl;
std::cout << "Phone Number: " << phone_number << std::endl;
}
};
int main() {
int n;
std::cout << "Enter the number of students: ";
std::cin >> n;
std::vector<Student> students;
for (int i = 0; i < n; ++i) {
int reg_num;
std::string name, program, phone;
std::cout << "\nEnter details for student " << i + 1 << ":\n";
std::cout << "Register Number: ";
std::cin >> reg_num;
std::cin.ignore(); // Ignore newline character in buffer
std::cout << "Student Name: ";
std::getline(std::cin, name);
std::cout << "Programme Name: ";
std::getline(std::cin, program);
std::cout << "Phone Number: ";
std::getline(std::cin, phone);
students.emplace_back(reg_num, name, program, phone);
}
std::cout << "\nDetails of " << n << " students:\n";
for (const auto& student : students) {
student.printDetails();
std::cout << std::endl;
}
return 0;
}
b). Write a program to implement the Stack using arrays. Write Push (), Pop(), and
Display() methods to demonstrate its working.
#include <iostream>
#define MAX_SIZE 100
class Stack {
private:
int top;
int arr[MAX_SIZE];
public:
Stack() {
top = -1; // Initializing top to -1 indicates an empty stack
}
bool isEmpty() {
return top == -1;
}
bool isFull() {
return top == MAX_SIZE - 1;
}
void push(int value) {
if (isFull()) {
std::cout << "Stack Overflow! Cannot push more elements.\n";
return;
}
arr[++top] = value;
std::cout << value << " pushed to stack.\n";
}
void pop() {
if (isEmpty()) {
std::cout << "Stack Underflow! Cannot pop from an empty stack.\n";
return;
}
std::cout << arr[top--] << " popped from stack.\n";
}
void display() {
if (isEmpty()) {
std::cout << "Stack is empty.\n";
return;
}
std::cout << "Stack elements: ";
for (int i = 0; i <= top; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
};
int main() {
Stack stack;
// Pushing elements onto the stack
stack.push(5);
stack.push(10);
stack.push(15);
stack.push(20);
// Displaying the stack
std::cout << "\nAfter pushing elements:\n";
stack.display();
// Popping elements from the stack
stack.pop();
stack.pop();
// Displaying the stack after popping
std::cout << "\nAfter popping elements:\n";
stack.display();
return 0;
}
2. a). Design a superclass called Staff with details as StaffId, Name, Phone, Salary. Extend
this class by writing three subclasses namely Teaching (domain, publications), Technical
(skills), and Contract (period). Write a CPP program to read and display at least 3 staff
objects of all three categories.
#include <iostream>
#include <string>
class Staff {
protected:
int staffId;
std::string name;
std::string phone;
double salary;
public:
Staff(int id, const std::string& n, const std::string& p, double sal)
: staffId(id), name(n), phone(p), salary(sal) {}
void display() const {
std::cout << "Staff ID: " << staffId << std::endl;
std::cout << "Name: " << name << std::endl;
std::cout << "Phone: " << phone << std::endl;
std::cout << "Salary: $" << salary << std::endl;
}
};
class Teaching : public Staff {
private:
std::string domain;
int publications;
public:
Teaching(int id, const std::string& n, const std::string& p, double sal, const std::string& dom,
int pub)
: Staff(id, n, p, sal), domain(dom), publications(pub) {}
void display() const {
std::cout << "\nTeaching Staff Details:\n";
Staff::display();
std::cout << "Domain: " << domain << std::endl;
std::cout << "Publications: " << publications << std::endl;
}
};
class Technical : public Staff {
private:
std::string skills;
public:
Technical(int id, const std::string& n, const std::string& p, double sal, const std::string& sk)
: Staff(id, n, p, sal), skills(sk) {}
void display() const {
std::cout << "\nTechnical Staff Details:\n";
Staff::display();
std::cout << "Skills: " << skills << std::endl;
}
};
class Contract : public Staff {
private:
int period;
public:
Contract(int id, const std::string& n, const std::string& p, double sal, int per)
: Staff(id, n, p, sal), period(per) {}
void display() const {
std::cout << "\nContract Staff Details:\n";
Staff::display();
std::cout << "Contract Period: " << period << " months" << std::endl;
}
};
int main() {
// Creating teaching staff objects
Teaching teacher1(101, "John Doe", "123-456-7890", 50000, "Computer Science", 5);
Teaching teacher2(102, "Jane Smith", "987-654-3210", 55000, "Physics", 3);
Teaching teacher3(103, "Alice Johnson", "111-222-3333", 48000, "Mathematics", 7);
// Creating technical staff objects
Technical tech1(201, "Bob Brown", "555-666-7777", 60000, "Programming");
Technical tech2(202, "Sara Lee", "888-999-0000", 62000, "Networking");
// Creating contract staff objects
Contract contract1(301, "Tom Wilson", "444-333-2222", 35000, 12);
Contract contract2(302, "Emily Clark", "666-777-8888", 38000, 6);
// Displaying staff details
std::cout << "Staff Details:\n";
teacher1.display();
teacher2.display();
teacher3.display();
tech1.display();
tech2.display();
contract1.display();
contract2.display();
return 0;
}
b). Write a class called Customer to store their name and date_of_birth. The date_of_birth
format should be dd/mm/yyyy. Write methods to read customer data as and display as
using StringTokenizer class considering the delimiter character as “/”.
#include <iostream>
#include <string>
#include <sstream>
class Customer {
private:
std::string name;
int day, month, year;
public:
// Constructor
Customer(const std::string& n, int d, int m, int y)
: name(n), day(d), month(m), year(y) {}
// Method to read customer data
void readData(const std::string& data) {
std::istringstream ss(data);
std::string token;
// Tokenizing using '/' as delimiter
getline(ss, token, '/');
name = token;
getline(ss, token, '/');
day = std::stoi(token);
getline(ss, token, '/');
month = std::stoi(token);
getline(ss, token, '/');
year = std::stoi(token);
}
// Method to display customer data
void displayData() const {
std::cout << "Name: " << name << std::endl;
std::cout << "Date of Birth: " << day << "/" << month << "/" << year << std::endl;
}
};
int main() {
Customer customer1("", 0, 0, 0);
Customer customer2("", 0, 0, 0);
std::string data1 = "John/15/03/1990";
std::string data2 = "Alice/25/07/1985";
// Reading and displaying customer data
customer1.readData(data1);
customer2.readData(data2);
std::cout << "Customer 1:\n";
customer1.displayData();
std::cout << std::endl;
std::cout << "Customer 2:\n";
customer2.displayData();
return 0;
}
3. a). Write a program to read two integers a andb. Compute a/b and print, when b is not
zero. Raise an exception when b is equal to zero.
#include <iostream>
#include <stdexcept>
int main() {
int a, b;
// Read two integers
std::cout << "Enter two integers (a and b): ";
std::cin >> a >> b;
try {
// Check if b is zero
if (b == 0) {
throw std::runtime_error("Error: Division by zero!");
}
// Compute a/b and print the result
double result = static_cast<double>(a) / b;
std::cout << "Result of a/b: " << result << std::endl;
} catch (const std::runtime_error& e) {
// Catch the exception and print the error message
std::cerr << e.what() << std::endl;
}
return 0;
}
b). Write a program that implements a multi-thread application that has three threads.
First thread generates a random integer for every 1 second; second thread computes the
square of the number and prints; third thread will print the value of cube of the number.
#include <iostream>
#include <thread>
#include <chrono>
#include <random>
#include <mutex>
std::mutex mtx; // Mutex for synchronization
void generateRandomNumber() {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(1, 100);
while (true) {
int randomNumber = dis(gen);
{
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Generated number: " << randomNumber << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void computeSquare() {
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
int randomNumber = std::rand() % 100 + 1;
{
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Square: " << randomNumber * randomNumber << std::endl;
}
}
}
void computeCube() {
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
int randomNumber = std::rand() % 100 + 1;
{
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Cube: " << randomNumber * randomNumber * randomNumber <<
std::endl;
}
}
}
int main() {
std::thread t1(generateRandomNumber);
std::thread t2(computeSquare);
std::thread t3(computeCube);
t1.join();
t2.join();
t3.join();
return 0;
}
4. Sort a given set of n integer elements using Quick Sort method and compute its time
complexity. Run the program for varied values of n> 5000 and record the time taken to
sort. Plot a graph of the time taken versus non graph sheet. The elements can be read from
a file or can be generated using the random number generator. Demonstrate using CPP
how the divide-and-conquer method works along with its time complexity analysis: worst
case, average case and best case.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <chrono>
// Function to partition the array
int partition(std::vector<int>& arr, int low, int high) {
int pivot = arr[high]; // Choose the pivot as the last element
int i = low - 1; // Index of smaller element
for (int j = low; j < high; j++) {
// If current element is smaller than or equal to pivot
if (arr[j] <= pivot) {
i++; // Increment index of smaller element
std::swap(arr[i], arr[j]);
}
}
std::swap(arr[i + 1], arr[high]);
return i + 1;
}
// Function to perform Quick Sort
void quickSort(std::vector<int>& arr, int low, int high) {
if (low < high) {
// Partitioning index
int pi = partition(arr, low, high);
// Separately sort elements before and after partition
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
// Initialize random number generator
std::srand(std::time(0));
// Generate random input
int n;
std::cout << "Enter the number of elements: ";
std::cin >> n;
std::vector<int> arr(n);
for (int i = 0; i < n; i++) {
arr[i] = std::rand() % 10000; // Random integers between 0 and 9999
}
// Start the clock
auto start = std::chrono::high_resolution_clock::now();
// Sort the array
quickSort(arr, 0, n - 1);
// End the clock
auto end = std::chrono::high_resolution_clock::now();
// Calculate the elapsed time
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
// Print the sorted array
std::cout << "Sorted array:" << std::endl;
for (int i = 0; i < n; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
// Print the time taken for sorting
std::cout << "Time taken for sorting: " << duration.count() << " microseconds" << std::endl;
return 0;
}
5. Sort a given set of n integer elements using Merge Sort method and compute its time
complexity. Run the program for varied values of n> 5000, and record the time taken to
sort. Plot a graph of the time taken versus non graph sheet. The elements can be read from
a file or can be generated using the random number generator. Demonstrate using CPP
how the divide-and-conquer method works along with its time complexity analysis: worst
case, average case and best case.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <chrono>
// Merge two subarrays of arr[]
void merge(std::vector<int>& arr, int l, int m, int r) {
int n1 = m - l + 1;
int n2 = r - m;
// Create temporary arrays
std::vector<int> L(n1), R(n2);
// Copy data to temporary arrays L[] and R[]
for (int i = 0; i < n1; i++)
L[i] = arr[l + i];
for (int j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
// Merge the temporary arrays back into arr[l..r]
int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
// Copy the remaining elements of L[], if any
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
// Copy the remaining elements of R[], if any
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
// Main function to perform Merge Sort
void mergeSort(std::vector<int>& arr, int l, int r) {
if (l < r) {
// Find the middle point
int m = l + (r - l) / 2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
// Merge the sorted halves
merge(arr, l, m, r);
}
}
int main() {
// Initialize random number generator
std::srand(std::time(0));
// Generate random input
int n;
std::cout << "Enter the number of elements: ";
std::cin >> n;
std::vector<int> arr(n);
for (int i = 0; i < n; i++) {
arr[i] = std::rand() % 10000; // Random integers between 0 and 9999
}
// Start the clock
auto start = std::chrono::high_resolution_clock::now();
// Sort the array using Merge Sort
mergeSort(arr, 0, n - 1);
// End the clock
auto end = std::chrono::high_resolution_clock::now();
// Calculate the elapsed time
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
// Print the sorted array
std::cout << "Sorted array:" << std::endl;
for (int i = 0; i < n; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
// Print the time taken for sorting
std::cout << "Time taken for sorting: " << duration.count() << " microseconds" << std::endl;
return 0;
}
6. Implement the Knapsack problem using
(a) Dynamic Programming method
#include <iostream>
#include <vector>
// Function to solve the 0/1 Knapsack problem
int knapsack(int W, std::vector<int>& wt, std::vector<int>& val, int n) {
std::vector<std::vector<int>> K(n + 1, std::vector<int>(W + 1, 0));
// Build table K[][] in bottom-up manner
for (int i = 0; i <= n; i++) {
for (int w = 0; w <= W; w++) {
if (i == 0 || w == 0)
K[i][w] = 0;
else if (wt[i - 1] <= w)
K[i][w] = std::max(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]);
else
K[i][w] = K[i - 1][w];
}
}
return K[n][W];
}
int main() {
int n; // Number of items
std::cout << "Enter the number of items: ";
std::cin >> n;
std::vector<int> val(n); // Values of items
std::vector<int> wt(n); // Weights of items
std::cout << "Enter the values of items:\n";
for (int i = 0; i < n; i++) {
std::cin >> val[i];
}
std::cout << "Enter the weights of items:\n";
for (int i = 0; i < n; i++) {
std::cin >> wt[i];
}
int W; // Capacity of knapsack
std::cout << "Enter the capacity of knapsack: ";
std::cin >> W;
int max_value = knapsack(W, wt, val, n);
std::cout << "Maximum value that can be obtained: " << max_value << std::endl;
return 0;
}
(b) Greedy method.
#include <iostream>
#include <vector>
#include <algorithm>
// Structure to represent an item
struct Item {
int value;
int weight;
};
// Comparator function to sort items in non-increasing order of value per unit weight
bool cmp(const Item& a, const Item& b) {
double valuePerUnitWeightA = (double)a.value / a.weight;
double valuePerUnitWeightB = (double)b.value / b.weight;
return valuePerUnitWeightA > valuePerUnitWeightB;
}
// Function to solve the Knapsack problem using Greedy method
double knapsackGreedy(int capacity, std::vector<Item>& items) {
// Sort items based on value per unit weight in non-increasing order
std::sort(items.begin(), items.end(), cmp);
double totalValue = 0.0;
double remainingCapacity = capacity;
// Iterate through sorted items and add them to the knapsack
for (const Item& item : items) {
if (remainingCapacity >= item.weight) {
totalValue += item.value;
remainingCapacity -= item.weight;
} else {
// Take a fraction of the item if it cannot be fully taken
double fraction = remainingCapacity / (double)item.weight;
totalValue += item.value * fraction;
break; // Stop iterating as knapsack is full
}
}
return totalValue;
}
int main() {
int capacity;
std::cout << "Enter the capacity of the knapsack: ";
std::cin >> capacity;
int n;
std::cout << "Enter the number of items: ";
std::cin >> n;
std::vector<Item> items(n);
std::cout << "Enter the value and weight of each item:\n";
for (int i = 0; i < n; ++i) {
std::cin >> items[i].value >> items[i].weight;
}
double maxValue = knapsackGreedy(capacity, items);
std::cout << "Maximum value that can be obtained: " << maxValue << std::endl;
return 0;
}
7. Write a program-from a given vertex in a weighted connected graph, find shortest paths
to other vertices using Dijkstra's algorithm..
#include <iostream>
#include <vector>
#include <queue>
#include <limits>
// Structure to represent an edge in the graph
struct Edge {
int to;
int weight;
};
// Structure to represent a vertex in the graph
struct Vertex {
std::vector<Edge> neighbors;
};
// Function to find shortest paths from a given source vertex to all other vertices using Dijkstra's
algorithm
std::vector<int> dijkstra(const std::vector<Vertex>& graph, int source) {
int n = graph.size(); // Number of vertices in the graph
std::vector<int> distance(n, std::numeric_limits<int>::max()); // Initialize distances to infinity
distance[source] = 0; // Distance from source to itself is 0
// Priority queue to store vertices based on their distances from the source
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>,
std::greater<std::pair<int, int>>> pq;
pq.push({0, source}); // Push the source vertex into the priority queue
// Dijkstra's algorithm
while (!pq.empty()) {
int u = pq.top().second; // Extract the vertex with the minimum distance
pq.pop();
// Update distances to all neighbors of u
for (const Edge& edge : graph[u].neighbors) {
int v = edge.to;
int weight = edge.weight;
if (distance[u] + weight < distance[v]) {
distance[v] = distance[u] + weight;
pq.push({distance[v], v});
}
}
}
return distance;
}
int main() {
// Example graph represented as an adjacency list
std::vector<Vertex> graph = {
{{ {1, 4}, {2, 1} }}, // Vertex 0
{{ {0, 4}, {2, 2}, {3, 5} }}, // Vertex 1
{{ {0, 1}, {1, 2}, {3, 2} }}, // Vertex 2
{{ {1, 5}, {2, 2} }} // Vertex 3
};
int source;
std::cout << "Enter the source vertex: ";
std::cin >> source;
// Find shortest paths from the source vertex
std::vector<int> distances = dijkstra(graph, source);
// Print shortest distances to all vertices
std::cout << "Shortest distances from vertex " << source << " to all other vertices:\n";
for (int i = 0; i < distances.size(); ++i) {
if (i != source) {
std::cout << "Vertex " << i << ": " << distances[i] << std::endl;
}
}
return 0;
}
8. Find Minimum Cost Spanning Tree of a given connected undirected graph using
Kruskal's algorithm. Use Union-Find algorithms in your program.
#include <iostream>
#include <vector>
#include <algorithm>
// Structure to represent an edge in the graph
struct Edge {
int src, dest, weight;
};
// Structure to represent a subset for Union-Find
struct Subset {
int parent;
int rank;
};
// Function to find the set of an element 'i' using path compression
int find(std::vector<Subset>& subsets, int i) {
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// Function to perform union of two sets of x and y using rank
void Union(std::vector<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++;
}
}
// Comparator function to sort edges based on weight
bool compareEdges(const Edge& a, const Edge& b) {
return a.weight < b.weight;
}
// Function to find Minimum Cost Spanning Tree (MST) using Kruskal's algorithm
std::vector<Edge> kruskalMST(std::vector<Edge>& edges, int V) {
std::vector<Edge> MST;
std::vector<Subset> subsets(V);
// Initialize subsets
for (int i = 0; i < V; i++) {
subsets[i].parent = i;
subsets[i].rank = 0;
}
// Sort edges by weight
std::sort(edges.begin(), edges.end(), compareEdges);
int edgeCount = 0, i = 0;
while (edgeCount < V - 1 && i < edges.size()) {
Edge nextEdge = edges[i++];
int x = find(subsets, nextEdge.src);
int y = find(subsets, nextEdge.dest);
if (x != y) {
MST.push_back(nextEdge);
Union(subsets, x, y);
edgeCount++;
}
}
return MST;
}
int main() {
int V, E;
std::cout << "Enter the number of vertices and edges: ";
std::cin >> V >> E;
std::vector<Edge> edges(E);
std::cout << "Enter source, destination, and weight of each edge:\n";
for (int i = 0; i < E; i++) {
std::cin >> edges[i].src >> edges[i].dest >> edges[i].weight;
}
std::vector<Edge> MST = kruskalMST(edges, V);
std::cout << "Minimum Cost Spanning Tree (MST):\n";
for (const Edge& edge : MST) {
std::cout << edge.src << " - " << edge.dest << " : " << edge.weight << std::endl;
}
return 0;
}
9. Find Minimum Cost Spanning Tree of a given connected undirected graph using Prim's
algorithm.
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
// Structure to represent an edge in the graph
struct Edge {
int to;
int weight;
};
// Structure to represent a vertex in the graph
struct Vertex {
std::vector<Edge> neighbors;
bool visited;
};
// Function to find the Minimum Cost Spanning Tree (MST) using Prim's algorithm
std::vector<Edge> primMST(const std::vector<Vertex>& graph, int start) {
int n = graph.size();
std::vector<Edge> MST;
std::vector<bool> visited(n, false);
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>,
std::greater<std::pair<int, int>>> pq;
visited[start] = true;
for (const Edge& edge : graph[start].neighbors) {
pq.push({edge.weight, edge.to});
}
while (!pq.empty()) {
int weight = pq.top().first;
int u = pq.top().second;
pq.pop();
if (visited[u]) continue;
visited[u] = true;
MST.push_back({start, u, weight});
for (const Edge& edge : graph[u].neighbors) {
int v = edge.to;
if (!visited[v]) {
pq.push({edge.weight, v});
}
}
}
return MST;
}
int main() {
// Example graph represented as an adjacency list
std::vector<Vertex> graph = {
{{ {1, 2}, {2, 3} }}, // Vertex 0
{{ {0, 2}, {2, 2}, {3, 4} }}, // Vertex 1
{{ {0, 3}, {1, 2}, {3, 1} }}, // Vertex 2
{{ {1, 4}, {2, 1} }} // Vertex 3
};
int start;
std::cout << "Enter the starting vertex: ";
std::cin >> start;
// Find Minimum Cost Spanning Tree (MST) using Prim's algorithm
std::vector<Edge> MST = primMST(graph, start);
// Print Minimum Cost Spanning Tree (MST)
std::cout << "Minimum Cost Spanning Tree (MST):\n";
int totalWeight = 0;
for (const Edge& edge : MST) {
std::cout << edge.to << " - " << edge.weight << std::endl;
totalWeight += edge.weight;
}
std::cout << "Total weight of MST: " << totalWeight << std::endl;
return 0;
}
10. Write programs to
(a) Implement All-Pairs Shortest Paths problem using Floyd's algorithm.
#include <iostream>
#include <vector>
#include <limits>
using namespace std;
const int INF = numeric_limits<int>::max();
vector<vector<int>> floydWarshall(const vector<vector<int>>& graph) {
int n = graph.size();
vector<vector<int>> dist(graph);
for (int k = 0; k < n; ++k) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (dist[i][k] != INF && dist[k][j] != INF && dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
return dist;
}
int main() {
// Example usage
vector<vector<int>> graph = {
{0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0}
};
vector<vector<int>> shortestDistances = floydWarshall(graph);
// Print shortest distances
for (auto& row : shortestDistances) {
for (int distance : row) {
if (distance == INF) {
cout << "INF ";
} else {
cout << distance << " ";
}
}
cout << endl;
}
return 0;
}
(b) Implement Travelling Sales Person problem using Dynamic programming.
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <limits>
const int INF = std::numeric_limits<int>::max();
// Function to calculate the distance between two points (cities)
double distance(const std::pair<int, int>& p1, const std::pair<int, int>& p2) {
return std::sqrt(std::pow(p1.first - p2.first, 2) + std::pow(p1.second - p2.second, 2));
}
// Function to solve the Travelling Salesman Problem using Dynamic Programming
double tspDynamicProgramming(const std::vector<std::pair<int, int>>& cities) {
int n = cities.size();
std::vector<std::vector<double>> dp(1 << n, std::vector<double>(n, INF));
// Base case: If there is only one city
dp[1][0] = 0;
// Dynamic programming loop
for (int mask = 1; mask < (1 << n); ++mask) {
for (int last = 0; last < n; ++last) {
if (mask & (1 << last)) {
for (int cur = 0; cur < n; ++cur) {
if (mask != (1 << cur) && (mask & (1 << cur))) {
dp[mask][cur] = std::min(dp[mask][cur], dp[mask ^ (1 << cur)][last] +
distance(cities[last], cities[cur]));
}
}
}
}
}
// Finding the minimum cost of the cycle
double minCost = INF;
for (int i = 1; i < n; ++i) {
minCost = std::min(minCost, dp[(1 << n) - 1][i] + distance(cities[i], cities[0]));
}
return minCost;
}
int main() {
int n;
std::cout << "Enter the number of cities: ";
std::cin >> n;
std::vector<std::pair<int, int>> cities(n);
std::cout << "Enter the coordinates of each city:\n";
for (int i = 0; i < n; ++i) {
std::cin >> cities[i].first >> cities[i].second;
}
double minCost = tspDynamicProgramming(cities);
std::cout << "Minimum cost of the tour: " << minCost << std::endl;
return 0;
}
11. Design and implement in CPP, to 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. For example, if S ={1, 2,
5, 6, 8} and d= 9, there are two solutions {1,2,6}and {1,8}. Display a suitable message, if the
given problem instance doesn't have a solution
#include <iostream>
#include <vector>
// Function to find a subset of a given set whose sum is equal to a given positive integer
void findSubset(const std::vector<int>& set, int n, int targetSum) {
std::vector<std::vector<bool>> dp(n + 1, std::vector<bool>(targetSum + 1, false));
// Base case: subset sum with sum 0 is always possible
for (int i = 0; i <= n; ++i)
dp[i][0] = true;
// Fill the dp table
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= targetSum; ++j) {
if (j < set[i - 1])
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - set[i - 1]];
}
}
// Retrieve the subset
if (dp[n][targetSum]) {
std::cout << "Subset with sum " << targetSum << " found: {";
int i = n, j = targetSum;
while (i > 0 && j > 0) {
if (dp[i][j] == dp[i - 1][j])
--i;
else {
std::cout << set[i - 1];
j -= set[i - 1];
if (j > 0) std::cout << ",";
--i;
}
}
std::cout << "}" << std::endl;
} else {
std::cout << "No subset found with sum " << targetSum << std::endl;
}
}
int main() {
std::vector<int> set = {1, 2, 5, 6, 8};
int targetSum = 9;
findSubset(set, set.size(), targetSum);
return 0;
}
12. Design and implement in CPP to find all Hamiltonian Cycles in a connected undirected
Graph G of n vertices using backtracking principle.
#include <iostream>
#include <vector>
#include <algorithm>
class Graph {
private:
int V; // Number of vertices
std::vector<std::vector<int>> adj; // Adjacency list
// Function to check if vertex v can be added at index 'pos' in the Hamiltonian cycle
bool isSafe(int v, const std::vector<int>& path, int pos) {
// Check if vertex v is adjacent to the previously added vertex in the path
if (!adj[path[pos - 1]][v])
return false;
// Check if vertex v is already included in the path
for (int i = 0; i < pos; ++i)
if (path[i] == v)
return false;
return true;
}
// Function to recursively find Hamiltonian cycle starting from the vertex 'pos'
bool hamiltonianCycleUtil(std::vector<int>& path, int pos) {
// If all vertices are included in the path, and the last vertex is adjacent to the first vertex,
then it's a Hamiltonian cycle
if (pos == V) {
if (adj[path[pos - 1]][path[0]] == 1)
return true;
else
return false;
}
for (int v = 1; v < V; ++v) {
if (isSafe(v, path, pos)) {
path[pos] = v;
if (hamiltonianCycleUtil(path, pos + 1))
return true;
path[pos] = -1; // Backtrack
}
}
return false;
}
public:
Graph(int vertices) : V(vertices), adj(vertices, std::vector<int>(vertices, 0)) {}
// Function to add an edge to the graph
void addEdge(int u, int v) {
adj[u][v] = 1;
adj[v][u] = 1;
}
// Function to find all Hamiltonian cycles in the graph
void findHamiltonianCycles() {
std::vector<int> path(V, -1);
// Add the first vertex to the path
path[0] = 0;
if (!hamiltonianCycleUtil(path, 1)) {
std::cout << "No Hamiltonian cycle exists in the graph\n";
return;
}
std::cout << "Hamiltonian cycles in the graph:\n";
do {
for (int v : path)
std::cout << v << " ";
std::cout << path[0] << "\n";
} while (std::next_permutation(path.begin() + 1, path.end())); // Generate all permutations
of the remaining vertices
}
};
int main() {
Graph g(5); // Create a graph with 5 vertices
// Add edges to the graph
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(0, 3);
g.addEdge(0, 4);
g.addEdge(1, 2);
g.addEdge(1, 3);
g.addEdge(1, 4);
g.addEdge(2, 3);
g.addEdge(2, 4);
g.addEdge(3, 4);
// Find and print all Hamiltonian cycles in the graph
g.findHamiltonianCycles();
return 0;
}