WEEK 7 solution
Q1:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define V 6 // Number of vertices in the graph
// Function to find the vertex with minimum distance value, from the set of vertices not yet
included in shortest path tree
int minDistance(int dist[], int sptSet[]) {
int min = INT_MAX, min_index;
for (int v = 0; v < V; v++)
if (sptSet[v] == 0 && dist[v] <= min)
min = dist[v], min_index = v;
return min_index;
}
// Function to print the final shortest path from source vertex to all other vertices
void printSolution(int dist[]) {
printf("Vertex \t\t Distance from Source\n");
for (int i = 0; i < V; i++)
printf("%d \t\t %d\n", i, dist[i]);
}
// Function that implements Dijkstra's single source shortest path algorithm for a graph
represented using adjacency matrix representation
void dijkstra(int graph[V][V], int src) {
int dist[V]; // The output array. dist[i] will hold the shortest distance from src to i
int sptSet[V]; // sptSet[i] will be 1 if vertex i is included in shortest path tree or shortest distance
from src to i is finalized
// Initialize all distances as INFINITE and sptSet[] as 0
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = 0;
// Distance of source vertex from itself is always 0
dist[src] = 0;
// Find shortest path for all vertices
for (int count = 0; count < V - 1; count++) {
// Pick the minimum distance vertex from the set of vertices not yet processed.
int u = minDistance(dist, sptSet);
// Mark the picked vertex as processed
sptSet[u] = 1;
// Update dist value of the adjacent vertices of the picked vertex.
for (int v = 0; v < V; v++)
if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
// print the constructed distance array
printSolution(dist);
}
int main() {
int graph[V][V] = { {0, 7, 9, 0, 0, 14},
{7, 0, 10, 15, 0, 0},
{9, 10, 0, 11, 0, 2},
{0, 15, 11, 0, 6, 0},
{0, 0, 0, 6, 0, 9},
{14, 0, 2, 0, 9, 0} };
dijkstra(graph, 0); // Run Dijkstra's Algorithm with source vertex 0
return 0;
}
Q2:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define V 6 // Number of vertices in the graph
// Function to print the final shortest path from source vertex to all other vertices
void printSolution(int dist[]) {
printf("Vertex \t\t Distance from Source\n");
for (int i = 0; i < V; i++)
printf("%d \t\t %d\n", i, dist[i]);
}
// Function that implements Bellman-Ford algorithm for a graph represented using adjacency
matrix representation
void bellmanFord(int graph[V][V], int src) {
int dist[V]; // The output array. dist[i] will hold the shortest distance from src to i
// Initialize distances from src to all other vertices as INFINITE
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[src] = 0;
// Relax all edges V-1 times. A simple shortest path from src to any other vertex can have at
most V-1 edges
for (int i = 0; i < V - 1; i++) {
for (int u = 0; u < V; u++) {
for (int v = 0; v < V; v++) {
if (graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
}
}
// Check for negative-weight cycles. If we get a shorter path, then there is a cycle
for (int u = 0; u < V; u++) {
for (int v = 0; v < V; v++) {
if (graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v]) {
printf("Graph contains negative-weight cycle\n");
return;
}
}
}
// print the constructed distance array
printSolution(dist);
}
int main() {
int graph[V][V] = { {0, 6, 0, 0, 7, 0},
{0, 0, 5, -4, 8, -2},
{0, -2, 0, 0, 0, 0},
{2, 0, 7, 0, 0, 0},
{0, -3, 9, 2, 0, 0},
{0, 0, 0, 0, -5, 0} };
bellmanFord(graph, 0); // Run Bellman-Ford Algorithm with source vertex 0
return 0;
}
Q3:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define V 4 // Number of vertices in the graph
// Function to find the shortest path with exactly k edges from source to destination
int shortestPathWithKEdges(int graph[V][V], int src, int dest, int k) {
int dp[V][V][k+1]; // 3D array to store the shortest distance between each pair of vertices with k
edges on the path
// Initialize the 3D array with infinity for all pairs of vertices with k edges
for (int e = 0; e <= k; e++) {
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
dp[i][j][e] = INT_MAX;
}
}
}
// Initialize the 3D array with the weight of the direct edges between the vertices
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (graph[i][j] != 0) {
dp[i][j][1] = graph[i][j];
}
}
}
// Compute the shortest distance between each pair of vertices with exactly k edges on the
path
for (int e = 2; e <= k; e++) {
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
for (int x = 0; x < V; x++) {
if (graph[i][x] != 0 && dp[x][j][e-1] != INT_MAX) {
dp[i][j][e] = (dp[i][j][e] < dp[i][x][1] + dp[x][j][e-1]) ? dp[i][j][e] : (dp[i][x][1] + dp[x][j]
[e-1]);
}
}
}
}
}
// Return the shortest distance between the source and destination vertices with exactly k
edges on the path
return dp[src][dest][k];
}
int main() {
// The example graph from the assignment
int graph[V][V] = { {0, 10, 3, 0},
{0, 0, 0, 7},
{0, 0, 0, 6},
{0, 0, 0, 0} };
int src = 0; // Source vertex
int dest = 3; // Destination vertex
int k = 2; // Number of edges on the path
int shortestPath = shortestPathWithKEdges(graph, src, dest, k); // Find the weight of the
shortest path
if (shortestPath == INT_MAX) {
printf("There is no path with exactly %d edges from vertex %d to vertex %d\n", k, src, dest);
} else {
printf("The weight of the shortest path with exactly %d edges from vertex %d to vertex %d is
%d\n", k, src, dest, shortestPath);
}
return 0;
}
WEEK 8: Solution
Q1:
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>
#define MAX_CITIES 100
int minimum_cost(int graph[MAX_CITIES][MAX_CITIES], int num_cities) {
bool visited[MAX_CITIES] = { false };
int MST[MAX_CITIES];
int start_city = 0; // Starting city (can be any)
int min_cost = 0;
visited[start_city] = true;
int edges[MAX_CITIES];
int num_edges = 0;
for (int i = 0; i < num_cities; i++) {
if (graph[start_city][i] != 0) {
edges[num_edges++] = i;
}
}
while (num_edges > 0) {
int min_cost_edge = INT_MAX;
int min_cost_dest = -1;
for (int i = 0; i < num_edges; i++) {
int dest = edges[i];
if (!visited[dest] && graph[start_city][dest] < min_cost_edge) {
min_cost_edge = graph[start_city][dest];
min_cost_dest = dest;
}
}
if (min_cost_dest != -1) {
visited[min_cost_dest] = true;
MST[min_cost_dest] = min_cost_edge;
min_cost += min_cost_edge;
for (int i = 0; i < num_cities; i++) {
if (graph[min_cost_dest][i] != 0 && !visited[i]) {
edges[num_edges++] = i;
}
}
}
num_edges--;
edges[min_cost_dest] = edges[num_edges];
}
return min_cost;
}
int main() {
int num_cities;
printf("Enter the number of cities: ");
scanf("%d", &num_cities);
int graph[MAX_CITIES][MAX_CITIES];
printf("Enter the adjacency matrix:\n");
for (int i = 0; i < num_cities; i++) {
for (int j = 0; j < num_cities; j++) {
scanf("%d", &graph[i][j]);
}
}
int min_cost = minimum_cost(graph, num_cities);
printf("Minimum cost: %d\n", min_cost);
return 0;
}
Q2:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAX_CITIES 100
// Structure to represent an edge
struct Edge {
int src, dest, weight;
};
// Structure to represent a subset for union-find
struct Subset {
int parent;
int rank;
};
// Compare function used by qsort to sort edges based on weight
int compare(const void* a, const void* b) {
struct Edge* edge1 = (struct Edge*)a;
struct Edge* edge2 = (struct Edge*)b;
return edge1->weight - edge2->weight;
}
// Find the parent of a subset (with path compression)
int find(struct Subset subsets[], int i) {
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);
return subsets[i].parent;
}
// Union of two subsets (with union by rank)
void unionSets(struct Subset subsets[], int x, int
Q3:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAX_VERTICES 100
struct Edge {
int src, dest, weight;
};
struct Subset {
int parent;
int rank;
};
int compare(const void* a, const void* b) {
struct Edge* edge1 = (struct Edge*)a;
struct Edge* edge2 = (struct Edge*)b;
return edge2->weight - edge1->weight;
}
int find(struct Subset subsets[], int i) {
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);
return subsets[i].parent;
}
void unionSets(struct Subset subsets[], int x, int y) {
int xroot = find(subsets, x);
int yroot = find(subsets, y);
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
else {
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
int maximum_budget(struct Edge edges[], int num_edges, int num_vertices) {
struct Subset* subsets = (struct Subset*)malloc(num_vertices * sizeof(struct Subset));
int max_spanning_weight = 0;
for (int i = 0; i < num_vertices; i++) {
subsets[i].parent = i;
subsets[i].rank = 0;
}
qsort(edges, num_edges, sizeof(struct Edge), compare);
for (int i = 0; i < num_edges; i++) {
int src = edges[i].src;
int dest = edges[i].dest;
int src_parent = find(subsets, src);
int dest_parent = find(subsets, dest);
if (src_parent != dest_parent) {
max_spanning_weight += edges[i].weight;
unionSets(subsets, src_parent, dest_parent);
}
}
free(subsets);
return max_spanning_weight;
}
int main() {
int num_vertices;
printf("Enter the number of vertices in the graph: ");
scanf("%d", &num_vertices);
int num_edges = num_vertices * (num_vertices - 1) / 2;
struct Edge edges[num_edges];
int edge_index = 0;
printf("Enter the adjacency matrix:\n");
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < i; j++) {
int weight;
scanf("%
WEEK 9: Solutions
Q1:
#include <stdio.h>
#include <stdbool.h>
#define INF 9999
#define MAX_VERTICES 100
void floyd_warshall(int graph[MAX_VERTICES][MAX_VERTICES], int num_vertices) {
int dist[MAX_VERTICES][MAX_VERTICES];
// Initialize the distance matrix with the graph
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
dist[i][j] = graph[i][j];
}
}
// Perform the Floyd-Warshall algorithm
for (int k = 0; k < num_vertices; k++) {
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
if (dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
// Print the shortest distance matrix
printf("Shortest Distance Matrix:\n");
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
if (dist[i][j] == INF) {
printf("INF ");
} else {
printf("%d ", dist[i][j]);
}
}
printf("\n");
}
}
int main() {
int num_vertices;
printf("Enter the number of vertices in the graph: ");
scanf("%d", &num_vertices);
int graph[MAX_VERTICES][MAX_VERTICES];
printf("Enter the adjacency matrix:\n");
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
scanf("%d", &graph[i][j]);
}
}
floyd_warshall(graph, num_vertices);
return 0;
}
Q2:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
struct Item {
int weight;
int value;
double ratio;
};
int compare(const void* a, const void* b) {
struct Item* item1 = (struct Item*)a;
struct Item* item2 = (struct Item*)b;
return (item2->ratio - item1->ratio) > 0 ? 1 : -1;
}
void fractional_knapsack(struct Item items[], int num_items, int capacity) {
qsort(items, num_items, sizeof(struct Item), compare);
double total_value = 0.0;
double total_weight = 0.0;
for (int i = 0; i < num_items; i++) {
if (items[i].weight <= capacity) {
total_value += items[i].value;
total_weight += items[i].weight;
capacity -= items[i].weight;
} else {
total_value += (double)(items[i].value * capacity) / items[i].weight;
total_weight += capacity;
capacity = 0;
}
if (capacity == 0)
break;
}
printf("Maximum value: %.2lf\n", total_value);
printf("item-weight\n");
for (int i = 0; i < num_items; i++) {
if (items[i].weight <= capacity) {
printf("%d-%d\n", i + 1, items[i].weight);
} else {
printf("%d-%.1lf\n", i + 1, (double)(items[i].value * capacity) / items[i].weight);
}
if (capacity == 0)
break;
}
}
int main() {
int num_items;
printf("Enter the number of items: ");
scanf("%d", &num_items);
struct Item items[num_items];
printf("Enter the weights of the items: ");
for (int i = 0; i < num_items; i++) {
scanf("%d", &items[i].weight);
}
printf("Enter the values of the items: ");
for (int i = 0; i < num_items; i++) {
scanf("%d", &items[i].value);
}
int capacity;
printf("Enter the maximum capacity of the knapsack: ");
scanf("%d", &capacity);
for (int i = 0; i < num_items; i++) {
items[i].ratio = (double)items[i].value / items[i].weight;
}
fractional_knapsack(items, num_items, capacity);
return 0;
}
Q3:
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int minimum_computation_cost(int n, int arr[]) {
qsort(arr, n, sizeof(int), compare); // Sort the array in ascending order
int total_cost = 0;
while (n > 1) {
// Take the two smallest elements
int smallest1 = arr[0];
int smallest2 = arr[1];
// Calculate the cost of merging and add it to totalCost
total_cost += smallest1 + smallest2;
// Append the merged file size to arr
arr[1] = smallest1 + smallest2;
// Shift the elements in the array to remove the merged files
for (int i = 2; i < n; i++) {
arr[i - 1] = arr[i];
}
// Decrement the size of the array
n--;
// Sort the array again in ascending order
qsort(arr, n, sizeof(int), compare);
}
return total_cost;
}
int main() {
int n;
printf("Enter the size of the array: ");
scanf("%d", &n);
int arr[n];
printf("Enter the array elements: ");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
int cost = minimum_computation_cost(n, arr);
printf("Minimum computation cost to merge all files: %d\n", cost);
return 0;
}
WEEK 10: Solution
Q1:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int index;
int startTime;
int finishTime;
} Activity;
int compare(const void *a, const void *b) {
return ((Activity *)a)->finishTime - ((Activity *)b)->finishTime;
}
void selectNonConflictingActivities(int n, int startTimes[], int finishTimes[]) {
Activity activities[n];
for (int i = 0; i < n; i++) {
activities[i].index = i + 1;
activities[i].startTime = startTimes[i];
activities[i].finishTime = finishTimes[i];
}
qsort(activities, n, sizeof(Activity), compare);
int count = 1;
int lastSelected = 0;
printf("No. of non-conflicting activities: %d\n", count);
printf("List of selected activities: %d", activities[lastSelected].index);
for (int i = 1; i < n; i++) {
if (activities[i].startTime >= activities[lastSelected].finishTime) {
count++;
lastSelected = i;
printf(", %d", activities[i].index);
}
}
printf("\n");
}
int main() {
int n;
printf("Enter the number of activities: ");
scanf("%d", &n);
int startTimes[n];
printf("Enter the starting times of the activities: ");
for (int i = 0; i < n; i++) {
scanf("%d", &startTimes[i]);
}
int finishTimes[n];
printf("Enter the finishing times of the activities: ");
for (int i = 0; i < n; i++) {
scanf("%d", &finishTimes[i]);
}
selectNonConflictingActivities(n, startTimes, finishTimes);
return 0;
}
Q2:
#include <stdio.h>
void selectTasks(int n, int timeTaken[], int deadlines[]) {
int count = 0;
int selectedTasks[n];
int totalTime = 0;
for (int i = 0; i < n; i++) {
if (totalTime + timeTaken[i] <= deadlines[i]) {
count++;
selectedTasks[count - 1] = i + 1;
totalTime += timeTaken[i];
}
}
printf("Max number of tasks = %d\n", count);
printf("Selected task numbers: ");
for (int i = 0; i < count; i++) {
printf("%d", selectedTasks[i]);
if (i != count - 1)
printf(", ");
}
printf("\n");
}
int main() {
int n;
printf("Enter the total number of tasks: ");
scanf("%d", &n);
int timeTaken[n];
printf("Enter the time taken for each task: ");
for (int i = 0; i < n; i++) {
scanf("%d", &timeTaken[i]);
}
int deadlines[n];
printf("Enter the deadlines for each task: ");
for (int i = 0; i < n; i++) {
scanf("%d", &deadlines[i]);
}
selectTasks(n, timeTaken, deadlines);
return 0;
}
Q3:
#include <stdio.h>
#include <stdlib.h>
void findMajorityAndMedian(int n, int elements[]) {
int count = 0;
int candidate = 0;
for (int i = 0; i < n; i++) {
if (count == 0) {
candidate = elements[i];
count = 1;
} else if (elements[i] == candidate) {
count++;
} else {
count--;
}
}
count = 0;
for (int i = 0; i < n; i++) {
if (elements[i] == candidate) {
count++;
}
}
printf("Majority element: %s\n", (count > n / 2) ? "yes" : "no");
// Sorting the array in ascending order
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (elements[j] > elements[j + 1]) {
int temp = elements[j];
elements[j] = elements[j + 1];
elements[j + 1] = temp;
}
}
}
printf("Median: ");
if (n % 2 == 1) {
printf("%d\n", elements[n / 2]);
} else {
int median1 = elements[n / 2 - 1];
int median2 = elements[n / 2];
printf("%d\n", (median1 + median2) / 2);
}
}
int main() {
int n;
printf("Enter the size of the array: ");
scanf("%d", &n);
int elements[n];
printf("Enter the elements of the array: ");
for (int i = 0; i < n; i++) {
scanf("%d", &elements[i]);
}
findMajorityAndMedian(n, elements);
return 0;
}
WEEK 11: Solutions
Q1:
#include <stdio.h>
#include <limits.h>
#define MAX_SIZE 100
int matrixChainMultiplication(int n, int dimensions[][2]) {
int dp[MAX_SIZE][MAX_SIZE];
for (int i = 1; i <= n; i++) {
dp[i][i] = 0;
}
for (int chainLength = 2; chainLength <= n; chainLength++) {
for (int i = 1; i <= n - chainLength + 1; i++) {
int j = i + chainLength - 1;
dp[i][j] = INT_MAX;
for (int k = i; k < j; k++) {
int cost = dp[i][k] + dp[k+1][j] + dimensions[i-1][0] * dimensions[k][1] * dimensions[j][1];
if (cost < dp[i][j]) {
dp[i][j] = cost;
}
}
}
}
return dp[1][n];
}
int main() {
int n;
printf("Enter the number of matrices: ");
scanf("%d", &n);
int dimensions[MAX_SIZE][2];
printf("Enter the dimensions of the matrices:\n");
for (int i = 0; i < n; i++) {
scanf("%d %d", &dimensions[i][0], &dimensions[i][1]);
}
int minOperations = matrixChainMultiplication(n, dimensions);
printf("Minimum number of operations: %d\n", minOperations);
return 0;
}
Q2:
#include <stdio.h>
#define MAX_SIZE 100
int coinChange(int numCoins, int coinValues[], int N) {
int dp[MAX_SIZE] = {0};
dp[0] = 1;
for (int i = 0; i < numCoins; i++) {
for (int j = coinValues[i]; j <= N; j++) {
dp[j] += dp[j - coinValues[i]];
}
}
return dp[N];
}
int main() {
int numCoins;
printf("Enter the number of coins: ");
scanf("%d", &numCoins);
int coinValues[MAX_SIZE];
printf("Enter the values of the coins: ");
for (int i = 0; i < numCoins; i++) {
scanf("%d", &coinValues[i]);
}
int N;
printf("Enter the value of N: ");
scanf("%d", &N);
int numWays = coinChange(numCoins, coinValues, N);
printf("Number of ways: %d\n", numWays);
return 0;
}
Q3:
#include <stdio.h>
#include <stdbool.h>
#define MAX_SIZE 100
bool subsetSumPartition(int n, int set[]) {
int totalSum = 0;
for (int i = 0; i < n; i++) {
totalSum += set[i];
}
if (totalSum % 2 != 0) {
return false;
}
int targetSum = totalSum / 2;
bool dp[MAX_SIZE][MAX_SIZE] = {false};
dp[0][0] = true;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= targetSum; j++) {
dp[i][j] = dp[i-1][j];
if (j >= set[i-1]) {
dp[i][j] = dp[i][j] || dp[i-1][j-set[i-1]];
}
}
}
return dp[n][targetSum];
}
int main() {
int n;
printf("Enter the number of elements: ");
scanf("%d", &n);
int set[MAX_SIZE];
printf("Enter the elements of the set: ");
for (int i = 0; i < n; i++) {
scanf("%d", &set[i]);
}
bool isPossible = subsetSumPartition(n, set);
if (isPossible) {
printf("yes\n");
} else {
printf("no\n");
}
return 0;
}