├── Base Codes ├── FloydWarshall.java ├── FractionalKnapSack.java ├── KnapSack01.java ├── Kosaraju.java ├── MCM.java ├── OBST.java └── Prims.java ├── Concept Builder - Practice.xlsx ├── Concept Builder 1-7.pdf ├── Lab 1 - Prim’s and Kruskal’s ├── Class Exercise - 1.java └── Class Exercise - 2.java ├── Lab 2 - Strongly Connected Graph ├── Challenge Yourself.java ├── Class Exercise - 1.java ├── Class Exercise - 2.java └── Practice At Home.java ├── Lab 3-Greedy&Dynamic Programming ├── Challenge Yourself.java ├── Class Exercise.java └── Practice At Home.java ├── Lab 4 - Optimal Ordering ├── Challenge Yourself.java ├── Class Exercise.java └── Practice At Home.java ├── Lab 5 - Shortest Path Algorithm ├── Challenge Yourself.java ├── Class Exercise.java └── Practice At Home.java ├── Lab 6 - Binary Search Tree ├── Challenge Yourself.java ├── Class Exercise.java └── Practice At Home.java ├── Lab 7 - 0 └── 1 Knapsack │ ├── Challenge Yourself.java │ ├── Class Exercise.java │ └── Practice At Home.java └── README.md /Base Codes/FloydWarshall.java: -------------------------------------------------------------------------------- 1 | 2 | import java.util.*; 3 | 4 | public class FloydWarshall { //Lab 5 5 | 6 | public static void main(String[] args) { 7 | Scanner sc = new Scanner(System.in); 8 | int V = sc.nextInt(); 9 | int arr[][] = new int[V][V]; 10 | 11 | for (int i = 0; i < V; i++) { 12 | for (int j = 0; j < V; j++) { 13 | arr[i][j] = sc.nextInt(); 14 | } 15 | } 16 | 17 | for (int k = 0; k < V; k++) { 18 | for (int i = 0; i < V; i++) { 19 | for (int j = 0; j < V; j++) { 20 | if(arr[i][k]!=999 && arr[k][j]!=999) 21 | arr[i][j]=Math.min(arr[i][j],arr[i][k]+arr[k][j]); 22 | } 23 | } 24 | } 25 | 26 | 27 | for (int i = 0; i < V; i++) { 28 | for (int j = 0; j < V; j++) { 29 | System.out.print(arr[i][j]==999?"INF ":arr[i][j]+" "); 30 | } 31 | System.out.println(); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Base Codes/FractionalKnapSack.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class FractionalKnapSack { //Lab 3 3 | static class Pair{ 4 | int wt,val; 5 | double ratio; 6 | 7 | Pair(int wt,int val) 8 | { 9 | this.wt=wt; 10 | this.val=val; 11 | this.ratio=(double)this.val/this.wt; 12 | } 13 | } 14 | public static void main(String[] args) { 15 | Scanner sc=new Scanner(System.in); 16 | int n=sc.nextInt(); 17 | int W=sc.nextInt(); 18 | 19 | int wt[]=new int[n]; 20 | int val[]=new int[n]; 21 | 22 | for(int i=0;i() { 34 | public int compare(Pair p1,Pair p2) 35 | { 36 | return Double.compare(p2.ratio, p1.ratio); 37 | } 38 | }); 39 | 40 | double profit=0; 41 | for(int i=0;i=n) 27 | return 0; 28 | 29 | int include=0; 30 | if(wt[i]<=W) 31 | include+=helper(i+1,W-wt[i],wt,val,n)+val[i]; 32 | int exclude=helper(i+1,W,wt,val,n); 33 | 34 | return Math.max(include,exclude); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Base Codes/Kosaraju.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Solution { 4 | public void dfs(int node, int vis[], ArrayList> adjT, List component) { 5 | vis[node] = 1; 6 | component.add(node); // collect node in current SCC 7 | for (int y : adjT.get(node)) { 8 | if (vis[y] == 0) 9 | dfs(y, vis, adjT, component); 10 | } 11 | } 12 | 13 | public void dfs1(int node, int vis[], ArrayList> adj, Stack s) { 14 | vis[node] = 1; 15 | for (int y : adj.get(node)) { 16 | if (vis[y] == 0) 17 | dfs1(y, vis, adj, s); 18 | } 19 | s.push(node); 20 | } 21 | 22 | public int kosaraju(int V, ArrayList> adj) { 23 | Stack s = new Stack<>(); 24 | int vis1[] = new int[V]; 25 | 26 | // 1st pass: get finishing order 27 | for (int i = 0; i < V; i++) { 28 | if (vis1[i] == 0) { 29 | dfs1(i, vis1, adj, s); 30 | } 31 | } 32 | 33 | // Reverse graph 34 | ArrayList> adjT = new ArrayList<>(); 35 | for (int i = 0; i < V; i++) { 36 | adjT.add(new ArrayList<>()); 37 | } 38 | for (int i = 0; i < V; i++) { 39 | for (int y : adj.get(i)) 40 | adjT.get(y).add(i); 41 | } 42 | 43 | // 2nd pass: DFS in finishing order on transposed graph 44 | int count = 0; 45 | int vis[] = new int[V]; 46 | System.out.println("Strongly Connected Components:"); 47 | while (!s.isEmpty()) { 48 | int x = s.pop(); 49 | if (vis[x] == 0) { 50 | List component = new ArrayList<>(); 51 | dfs(x, vis, adjT, component); 52 | count++; 53 | System.out.println(component); 54 | } 55 | } 56 | return count; 57 | } 58 | 59 | // Main method 60 | public static void main(String[] args) { 61 | int V = 5; 62 | int[][] edges = { {0, 2}, {1, 0}, {2, 1}, {0, 3}, {3, 4} }; 63 | 64 | ArrayList> adj = new ArrayList<>(); 65 | for (int i = 0; i < V; i++) { 66 | adj.add(new ArrayList<>()); 67 | } 68 | 69 | for (int[] edge : edges) { 70 | adj.get(edge[0]).add(edge[1]); 71 | } 72 | 73 | Solution sol = new Solution(); 74 | int sccCount = sol.kosaraju(V, adj); 75 | 76 | System.out.println("Total SCCs: " + sccCount); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Base Codes/MCM.java: -------------------------------------------------------------------------------- 1 | 2 | import java.util.Scanner; 3 | 4 | public class MCM { // Lab 4 5 | 6 | static int dp[][]; 7 | static int bracket[][]; 8 | 9 | public static void main(String[] args) { 10 | Scanner sc = new Scanner(System.in); 11 | int n = sc.nextInt(); 12 | int dims[] = new int[n]; 13 | 14 | for (int i = 0; i < n; i++) { 15 | dims[i] = sc.nextInt(); 16 | } 17 | dp = new int[n][n]; 18 | bracket = new int[n][n]; 19 | 20 | for (int i = n - 1; i >=1; i--) { 21 | for (int j = i + 1; j < n; j++) { 22 | int mini = Integer.MAX_VALUE; 23 | for (int k = i; k < j; k++) { 24 | int steps = dp[i][k] + dp[k + 1][j] 25 | + dims[i - 1] * dims[k] * dims[j]; 26 | 27 | if (steps < mini) { 28 | mini = steps; 29 | bracket[i][j] = k; 30 | } 31 | } 32 | dp[i][j] = mini; 33 | } 34 | } 35 | System.out.println(dp[1][n - 1]); 36 | String name[] = new String[n - 1]; 37 | for (int i = 0; i < name.length; i++) { 38 | name[i] = "M" + (i + 1); 39 | } 40 | StringBuilder result=new StringBuilder(); 41 | helper(1, n - 1, name,result); 42 | System.out.println(result); 43 | } 44 | 45 | public static void helper(int i, int j, String name[],StringBuilder result) { 46 | if (i == j) { 47 | result.append(name[i - 1]); 48 | return; 49 | } 50 | result.append("("); 51 | helper(i, bracket[i][j], name,result); 52 | result.append("x"); 53 | helper(bracket[i][j] + 1, j, name,result); 54 | result.append(")"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Base Codes/OBST.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class OBST { 4 | 5 | public static void main(String[] args) { 6 | Scanner sc = new Scanner(System.in); 7 | 8 | // Input: number of keys 9 | System.out.print("Enter number of keys: "); 10 | int n = sc.nextInt(); 11 | 12 | // Input: frequencies of each key 13 | int[] freq = new int[n]; 14 | System.out.println("Enter the frequencies:"); 15 | for (int i = 0; i < n; i++) { 16 | freq[i] = sc.nextInt(); 17 | } 18 | 19 | // dp[i][j] will store the minimum cost of OBST that can be formed from keys i to j 20 | int[][] dp = new int[n][n]; 21 | 22 | // gap represents the length of the subproblem (i.e., number of keys considered) 23 | for (int gap = 0; gap < n; gap++) { 24 | for (int i = 0, j = gap; j < n; i++, j++) { 25 | 26 | int sum = 0; 27 | for (int k = i; k <= j; k++) { 28 | sum += freq[k]; // total frequency in this range 29 | } 30 | 31 | int minCost = Integer.MAX_VALUE; 32 | 33 | // Try each key in the range [i..j] as root 34 | for (int r = i; r <= j; r++) { 35 | int leftCost = (r == i) ? 0 : dp[i][r - 1]; 36 | int rightCost = (r == j) ? 0 : dp[r + 1][j]; 37 | int totalCost = leftCost + rightCost + sum; 38 | 39 | if (totalCost < minCost) { 40 | minCost = totalCost; 41 | } 42 | } 43 | 44 | dp[i][j] = minCost; 45 | } 46 | } 47 | 48 | System.out.println("Minimum cost of OBST: " + dp[0][n - 1]); 49 | 50 | sc.close(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Base Codes/Prims.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class Prims //Lab 1 3 | { 4 | static class Edge implements Comparable{ 5 | int u,v,wt; 6 | Edge(int u,int v,int wt) 7 | { 8 | this.u=u; 9 | this.v=v; 10 | this.wt=wt; 11 | } 12 | public int compareTo(Edge e) 13 | { 14 | return this.wt-e.wt; 15 | } 16 | } 17 | public static void prims(int adj[][],int V) 18 | { 19 | boolean visited[]=new boolean[V]; 20 | ArrayList ans=new ArrayList<>(); 21 | PriorityQueue pq=new PriorityQueue<>(); 22 | 23 | visited[0]=true; 24 | int sum=0; 25 | 26 | for(int i=0;i0) 29 | pq.offer(new Edge(0, i, adj[0][i])); 30 | } 31 | while(!pq.isEmpty()) 32 | { 33 | Edge e=pq.poll(); 34 | int u=e.u; 35 | int v=e.v; 36 | int wt=e.wt; 37 | 38 | if(!visited[v]) 39 | { 40 | visited[v]=true; 41 | ans.add(e); 42 | sum+=wt; 43 | 44 | for(int i=0;i0 && !visited[i]) 47 | pq.offer(new Edge(v, i, adj[v][i])); 48 | } 49 | } 50 | } 51 | 52 | Collections.sort(ans,new Comparator(){ 53 | public int compare(Edge e1,Edge e2) 54 | { 55 | if(e1.v!=e2.v) 56 | return e1.v-e2.v; 57 | else 58 | return e1.u-e2.u; 59 | } 60 | }); 61 | 62 | System.out.println("Minimum Spanning Cost=>"+sum); 63 | System.out.println("u\tv\twt"); 64 | for(Edge e:ans) 65 | { 66 | System.out.println(e.u+"\t"+e.v+"\t"+e.wt); 67 | } 68 | } 69 | public static void main(String args[]) 70 | { 71 | Scanner sc=new Scanner(System.in); 72 | int V=sc.nextInt(); 73 | int E=sc.nextInt(); 74 | 75 | int adj[][]=new int[V][V]; 76 | for(int i=0;i 0) { 109 | int minDistance = INF; 110 | int v = -1; 111 | 112 | for (int i = 1; i < n; i++) { 113 | if (!visited[i] && distance[i] < minDistance) { 114 | v = i; 115 | minDistance = distance[i]; 116 | } 117 | } 118 | 119 | int u = from[v]; 120 | spanning[u][v] = distance[v]; 121 | spanning[v][u] = distance[v]; 122 | edges--; 123 | visited[v] = true; 124 | 125 | for (int i = 1; i < n; i++) { 126 | if (!visited[i] && cost[i][v] < distance[i]) { 127 | distance[i] = cost[i][v]; 128 | from[i] = v; 129 | } 130 | } 131 | 132 | minCost += cost[u][v]; 133 | } 134 | return minCost; 135 | } 136 | 137 | public void printSpanningTree() { 138 | System.out.println("Spanning Tree Matrix:"); 139 | for (int i = 0; i < n; i++) { 140 | for (int j = 0; j < n; j++) { 141 | System.out.print(spanning[i][j] + " "); 142 | } 143 | System.out.println(); 144 | } 145 | } 146 | 147 | public static void main(String[] args) { 148 | Scanner scanner = new Scanner(System.in); 149 | int n = scanner.nextInt(); 150 | PrimsAlgorithm primsAlgo = new PrimsAlgorithm(n); 151 | primsAlgo.readGraph(scanner); 152 | int totalCost = primsAlgo.prims(); 153 | primsAlgo.printSpanningTree(); 154 | System.out.print("Total Cost: " + totalCost); 155 | scanner.close(); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /Lab 2 - Strongly Connected Graph/Class Exercise - 1.java: -------------------------------------------------------------------------------- 1 | // 🖧 Problem Statement: Identifying Strongly Connected Components 2 | 3 | // David, a network administrator, is analyzing the connectivity of a directed network of servers. 4 | // He wants to find groups of servers that are **strongly connected** — 5 | // that is, there exists a **path from every server to every other server within the group**, and vice versa. 6 | 7 | // Your task is to write a program to identify all the **Strongly Connected Components (SCCs)** in the given directed graph. 8 | 9 | // 📥 Input Format: 10 | // • The first line contains an integer `V` — the number of servers (nodes). 11 | // • The second line contains an integer `E` — the number of directed connections (edges). 12 | // • The next `E` lines each contain two integers `u` and `v` representing a directed edge from server `u` to server `v`. 13 | 14 | // 📤 Output Format: 15 | // • Print `"Strongly Connected Components are:"` 16 | // • Then, for each SCC, print a single line containing the nodes in that component, space-separated. 17 | // • Each SCC can be printed in any order, and the nodes within a component can also be in any order. 18 | 19 | // 🔒 Constraints: 20 | // • 1 ≤ V ≤ 10 21 | // • 1 ≤ E ≤ 10 22 | 23 | // 🧪 Sample Test Case 1: 24 | // Input: 25 | // 4 26 | // 4 27 | // 1 2 28 | // 2 3 29 | // 3 4 30 | // 4 1 31 | 32 | // Output: 33 | // Strongly Connected Components are: 34 | // 1 2 3 4 35 | 36 | // 🧪 Sample Test Case 2: 37 | // Input: 38 | // 5 39 | // 5 40 | // 1 3 41 | // 1 4 42 | // 2 1 43 | // 3 2 44 | // 4 5 45 | 46 | // Output: 47 | // Strongly Connected Components are: 48 | // 1 2 3 49 | // 4 50 | // 5 51 | 52 | // 🧠 Explanation: 53 | // • In Sample 1, the graph forms a cycle: 1 → 2 → 3 → 4 → 1. So all nodes are part of one SCC. 54 | // • In Sample 2, nodes 1, 2, and 3 form a cycle. Node 4 can reach 5, but 5 cannot reach 4, so they form separate SCCs. 55 | 56 | import java.util.Scanner; 57 | 58 | public class Main { 59 | 60 | static final int MAX = 100; 61 | 62 | // Depth-First Search (DFS) to check if there's a path from curr to des 63 | static boolean dfs(int curr, int des, int[][] adj, int[] vis, int n) { 64 | if (curr == des) { 65 | return true; 66 | } 67 | vis[curr] = 1; 68 | for (int i = 1; i <= n; i++) { 69 | if (adj[curr][i] == 1 && vis[i] == 0) { 70 | if (dfs(i, des, adj, vis, n)) { 71 | return true; 72 | } 73 | } 74 | } 75 | return false; 76 | } 77 | 78 | // Helper function to check if there's a path between src and des 79 | static boolean isPath(int src, int des, int[][] adj, int n) { 80 | int[] vis = new int[MAX]; 81 | return dfs(src, des, adj, vis, n); 82 | } 83 | 84 | // Function to find and print the strongly connected components 85 | static void findSCC(int n, int[][] edges, int edgeCount) { 86 | int[][] adj = new int[MAX][MAX]; 87 | int[] is_scc = new int[MAX]; 88 | 89 | // Fill adjacency matrix 90 | for (int i = 0; i < edgeCount; i++) { 91 | adj[edges[i][0]][edges[i][1]] = 1; 92 | } 93 | 94 | System.out.println("Strongly Connected Components are:"); 95 | 96 | // Find SCCs 97 | for (int i = 1; i <= n; i++) { 98 | if (is_scc[i] == 0) { 99 | int[] scc = new int[MAX]; 100 | int scc_size = 0; 101 | scc[scc_size++] = i; 102 | 103 | for (int j = i + 1; j <= n; j++) { 104 | if (is_scc[j] == 0 && isPath(i, j, adj, n) && isPath(j, i, adj, n)) { 105 | is_scc[j] = 1; 106 | scc[scc_size++] = j; 107 | } 108 | } 109 | 110 | // Print the SCC 111 | for (int k = 0; k < scc_size; k++) { 112 | System.out.print(scc[k] + " "); 113 | } 114 | System.out.println(); 115 | } 116 | } 117 | } 118 | 119 | // Main function to take input and call the findSCC function 120 | public static void main(String[] args) { 121 | Scanner scanner = new Scanner(System.in); 122 | 123 | int V = scanner.nextInt(); // Number of servers (nodes) 124 | int E = scanner.nextInt(); // Number of connections (edges) 125 | 126 | int[][] edges = new int[MAX][2]; 127 | for (int i = 0; i < E; i++) { 128 | edges[i][0] = scanner.nextInt(); 129 | edges[i][1] = scanner.nextInt(); 130 | } 131 | 132 | // Find and print the strongly connected components 133 | findSCC(V, edges, E); 134 | 135 | scanner.close(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Lab 2 - Strongly Connected Graph/Class Exercise - 2.java: -------------------------------------------------------------------------------- 1 | // 🌍 Problem Statement: Counting Connected Terrain Components 2 | 3 | // Liam, a scientist, is analyzing a 2D grid where each cell represents a type of terrain (denoted by a character). 4 | // He needs to determine the number of **connected components** in the grid. A connected component is formed by 5 | // **adjacent cells (horizontally or vertically)** that have the **same terrain type**. 6 | 7 | // Your task is to write a program to help Liam count how many such connected components exist in the grid. 8 | 9 | // 📥 Input Format: 10 | // • The first line contains an integer `n` — the number of rows in the grid. 11 | // • The second line contains an integer `m` — the number of columns in the grid. 12 | // • The next `n` lines each contain a string of `m` lowercase characters, where each character represents a terrain type at that cell. 13 | 14 | // 📤 Output Format: 15 | // • Print a single integer — the number of connected components in the matrix. 16 | 17 | // 🔒 Constraints: 18 | // • 1 ≤ n, m ≤ 10 19 | // • Terrain types are lowercase letters (e.g., 'a', 'b', ..., 'j') 20 | 21 | // 🧪 Sample Test Case 1: 22 | // Input: 23 | // 3 24 | // 5 25 | // aabba 26 | // aabba 27 | // aaaca 28 | 29 | // Output: 30 | // 4 31 | 32 | // 🧪 Sample Test Case 2: 33 | // Input: 34 | // 4 35 | // 4 36 | // aaaa 37 | // abba 38 | // abba 39 | // aaaa 40 | 41 | // Output: 42 | // 2 43 | 44 | // 🧠 Explanation for Sample 2: 45 | // Grid: 46 | // a a a a 47 | // a b b a 48 | // a b b a 49 | // a a a a 50 | // 51 | // Component 1: All 'a' cells form one large connected component. 52 | // Component 2: All 'b' cells in the center form the second component. 53 | // So the total number of components is 2. 54 | 55 | 56 | import java.util.Scanner; 57 | 58 | class ConnectedComponents { 59 | 60 | static final int MAX_ROW = 500; 61 | static final int MAX_COL = 500; 62 | static boolean[][] visited = new boolean[MAX_ROW][MAX_COL]; 63 | 64 | // Function to check if it's safe to visit the cell 65 | static boolean isSafe(char[][] M, int row, int col, char c, int n, int l) { 66 | return (row >= 0 && row < n) && (col >= 0 && col < l) && (M[row][col] == c && !visited[row][col]); 67 | } 68 | 69 | // Depth First Search (DFS) function 70 | static void DFS(char[][] M, int row, int col, char c, int n, int l) { 71 | int[] rowNbr = {-1, 1, 0, 0}; 72 | int[] colNbr = {0, 0, 1, -1}; 73 | 74 | visited[row][col] = true; 75 | 76 | for (int k = 0; k < 4; ++k) { 77 | if (isSafe(M, row + rowNbr[k], col + colNbr[k], c, n, l)) { 78 | DFS(M, row + rowNbr[k], col + colNbr[k], c, n, l); 79 | } 80 | } 81 | } 82 | 83 | // Function to count the number of connected components 84 | static int connectedComponents(char[][] M, int n, int l) { 85 | int connectedComp = 0; 86 | 87 | for (int i = 0; i < n; i++) { 88 | for (int j = 0; j < l; j++) { 89 | if (!visited[i][j]) { 90 | char c = M[i][j]; 91 | DFS(M, i, j, c, n, l); 92 | connectedComp++; 93 | } 94 | } 95 | } 96 | return connectedComp; 97 | } 98 | 99 | public static void main(String[] args) { 100 | Scanner sc = new Scanner(System.in); 101 | int n = sc.nextInt(); 102 | int l = sc.nextInt(); 103 | char[][] M = new char[MAX_ROW][MAX_COL]; 104 | 105 | // Input the matrix 106 | for (int i = 0; i < n; i++) { 107 | String row = sc.next(); 108 | M[i] = row.toCharArray(); // Convert string to character array 109 | } 110 | 111 | // Get and print the number of connected components 112 | System.out.println(connectedComponents(M, n, l)); 113 | sc.close(); 114 | } 115 | } 116 | 117 | -------------------------------------------------------------------------------- /Lab 3-Greedy&Dynamic Programming/Challenge Yourself.java: -------------------------------------------------------------------------------- 1 | // Problem Statement 2 | // 3 | // You are a savvy thief preparing to rob a jewelry store. You have a knapsack with a limited capacity and a list of items, 4 | // each with a certain weight and a corresponding profit. 5 | // 6 | // Your objective is to maximize the total profit you can obtain by selecting items to place in your knapsack 7 | // while staying within its weight capacity. Write a program to help you calculate the maximum profit you can achieve. 8 | // 9 | // Note: Use the 0/1 knapsack method to solve the program. 10 | // 11 | // Example: 12 | // 13 | // Input: 14 | // 3 15 | // 60 10 16 | // 100 20 17 | // 120 30 18 | // 50 19 | // 20 | // Output: 21 | // 220 22 | // 23 | // Explanation: 24 | // By selecting the second and third items, you achieve a maximum profit of Rs. 220. 25 | // The sum of their profits (100 + 120) gives you the highest total profit while 26 | // not exceeding the knapsack's weight capacity of 50. 27 | // 28 | // Input format: 29 | // The first line contains an integer N, representing the number of items available in the store. 30 | // 31 | // Each of the next N lines contains two space-separated integers P and W, 32 | // where P is the profit that can be obtained by stealing the item and W is the weight of the item. 33 | // 34 | // The last line contains an integer C representing the weight capacity of your knapsack. 35 | // 36 | // Output format: 37 | // The output displays the maximum total profit that you can achieve by selecting items for your knapsack. 38 | // 39 | // Refer to the sample output for the formatting specifications. 40 | // 41 | // Code constraints: 42 | // The given test cases fall under the formatting specifications: 43 | // 44 | // 1 ≤ N ≤ 10 45 | // 46 | // 1 ≤ P, W ≤ 200 47 | // 48 | // 1 ≤ C ≤ 50 49 | // 50 | // Sample test cases: 51 | // 52 | // Input 1: 53 | // 3 54 | // 60 10 55 | // 100 20 56 | // 120 30 57 | // 50 58 | // 59 | // Output 1: 60 | // 220 61 | // 62 | // Input 2: 63 | // 2 64 | // 10 30 65 | // 20 60 66 | // 70 67 | // 68 | // Output 2: 69 | // 20 70 | 71 | import java.util.Scanner; 72 | import java.util.Arrays; 73 | 74 | class KnapsackProblem { 75 | 76 | static int[][] dp; // Memoization table 77 | 78 | public static int knapSack(int W, int[] wt, int[] val, int n) { 79 | if (n == 0 || W == 0) 80 | return 0; 81 | 82 | if (dp[n][W] != -1) // If already computed, return stored result 83 | return dp[n][W]; 84 | 85 | if (wt[n - 1] > W) 86 | return dp[n][W] = knapSack(W, wt, val, n - 1); 87 | 88 | return dp[n][W] = Math.max( 89 | val[n - 1] + knapSack(W - wt[n - 1], wt, val, n - 1), 90 | knapSack(W, wt, val, n - 1) 91 | ); 92 | } 93 | 94 | public static void main(String[] args) { 95 | Scanner scanner = new Scanner(System.in); 96 | int n = scanner.nextInt(); 97 | int[] profit = new int[n]; 98 | int[] weight = new int[n]; 99 | 100 | for (int i = 0; i < n; ++i) { 101 | profit[i] = scanner.nextInt(); 102 | weight[i] = scanner.nextInt(); 103 | } 104 | 105 | int W = scanner.nextInt(); 106 | 107 | dp = new int[n + 1][W + 1]; 108 | for (int[] row : dp) 109 | Arrays.fill(row, -1); // Initialize memoization table 110 | 111 | System.out.print(knapSack(W, weight, profit, n)); 112 | scanner.close(); 113 | } 114 | } 115 | 116 | // Problem Statement 117 | // 118 | // Maria runs a food delivery business with a van that has a limited weight capacity. 119 | // She needs to select ingredients in such a way that maximizes the total value of the delivery 120 | // without exceeding the van’s capacity. 121 | // 122 | // Your objective is to help Maria calculate: 123 | // 1. The maximum value of ingredients she can select for the delivery, 124 | // considering that she can take fractional amounts of the items (this is a fractional knapsack problem). 125 | // 2. The difference between the maximum value of selected ingredients and the total value of the ingredients. 126 | // 127 | // Example 128 | // 129 | // Input: 130 | // 4 10 131 | // 3 30 132 | // 4 50 133 | // 5 60 134 | // 6 70 135 | // 136 | // Output: 137 | // 121.67 138 | // 88.33 139 | // 140 | // Explanation: 141 | // Item Details: 142 | // Item 1: (Weight = 3 kg, Value = 30), 143 | // Item 2: (Weight = 4 kg, Value = 50), 144 | // Item 3: (Weight = 5 kg, Value = 60), 145 | // Item 4: (Weight = 6 kg, Value = 70). 146 | // 147 | // Value-to-Weight Ratios: 148 | // Item 2: 50/4 = 12.5, Item 3: 60/5 = 12.0, Item 4: 70/6 = 11.67, Item 1: 30/3 = 10.0. 149 | // 150 | // Sorted by Ratio: 151 | // Item 2 → Item 3 → Item 4 → Item 1. 152 | // 153 | // Greedy Selection: 154 | // - Take Item 2 (4 kg, value 50), 155 | // - Take Item 3 (5 kg, value 60), 156 | // - Take 1 kg from Item 4, yielding value 11.67. 157 | // 158 | // Total Selected Value: 159 | // 50 (Item 2) + 60 (Item 3) + 11.67 (part of Item 4) = 121.67. 160 | // 161 | // Total Value of All Items: 162 | // 30 (Item 1) + 50 (Item 2) + 60 (Item 3) + 70 (Item 4) = 210. 163 | // 164 | // Difference: 165 | // 210 - 121.67 = 88.33. 166 | // 167 | // Input format: 168 | // The first line contains two values: 169 | // - An integer N, representing the number of items available, 170 | // - A double W, representing the weight capacity of the van. 171 | // 172 | // The next N lines contain two space-separated integers: weight[i] and value[i], 173 | // representing the weight and value of each ingredient (after removing decimal points). 174 | // 175 | // Output format: 176 | // The output consists of two lines: 177 | // 1. The first line prints the double value representing the maximum value, rounded to two decimal places. 178 | // 2. The second line prints the difference between the maximum value and the total value of unselected ingredients, also rounded to two decimal places. 179 | // 180 | // Code constraints: 181 | // The given test cases fall under the following specifications: 182 | // 1 ≤ N ≤ 102 183 | // 1 ≤ weight[i], value[i] ≤ 102 184 | // 1 ≤ W ≤ 102 185 | // 186 | // Sample test cases: 187 | // 188 | // Input 1: 189 | // 4 10 190 | // 3 30 191 | // 4 50 192 | // 5 60 193 | // 6 70 194 | // 195 | // Output 1: 196 | // 121.67 197 | // 88.33 198 | // 199 | // Input 2: 200 | // 3 7 201 | // 3 30 202 | // 4 50 203 | // 5 60 204 | // 205 | // Output 2: 206 | // 86.00 207 | // 54.00 208 | 209 | 210 | 211 | import java.util.Scanner; 212 | import java.util.Arrays; 213 | import java.util.Comparator; 214 | 215 | class Item { 216 | int weight; 217 | int value; 218 | double valuePerWeight; 219 | 220 | Item(int weight, int value) { 221 | this.weight = weight; 222 | this.value = value; 223 | this.valuePerWeight = (double) value / weight; 224 | } 225 | } 226 | 227 | class FoodDeliveryKnapsack { 228 | 229 | // Comparator for sorting items by value-to-weight ratio in descending order 230 | public static class ItemComparator implements Comparator { 231 | @Override 232 | public int compare(Item item1, Item item2) { 233 | if (item1.valuePerWeight < item2.valuePerWeight) { 234 | return 1; 235 | } else if (item1.valuePerWeight > item2.valuePerWeight) { 236 | return -1; 237 | } 238 | return 0; 239 | } 240 | } 241 | 242 | public static double greedyKnapsack(int N, double W, Item[] items, double[] totalWeight) { 243 | double totalValue = 0.0; 244 | totalWeight[0] = 0.0; // Initialize total weight at index 0 245 | 246 | for (int i = 0; i < N; i++) { 247 | if (items[i].weight <= W) { 248 | W -= items[i].weight; 249 | totalValue += items[i].value; 250 | totalWeight[0] += items[i].weight; 251 | } else { 252 | totalValue += items[i].valuePerWeight * W; 253 | totalWeight[0] += W; 254 | break; 255 | } 256 | } 257 | return totalValue; 258 | } 259 | 260 | public static void main(String[] args) { 261 | Scanner sc = new Scanner(System.in); 262 | 263 | int N = sc.nextInt(); // Number of ingredients 264 | double W = sc.nextDouble(); // Weight capacity of the van 265 | 266 | Item[] items = new Item[N]; 267 | double totalValueOfAll = 0.0; 268 | 269 | for (int i = 0; i < N; i++) { 270 | int weight = sc.nextInt(); 271 | int value = sc.nextInt(); 272 | items[i] = new Item(weight, value); 273 | totalValueOfAll += value; 274 | } 275 | 276 | // Sorting items based on value-to-weight ratio in descending order 277 | Arrays.sort(items, new ItemComparator()); 278 | 279 | double[] totalWeight = new double[1]; // Using array to simulate passing by reference 280 | double maxValue = greedyKnapsack(N, W, items, totalWeight); 281 | 282 | double unselectedValue = totalValueOfAll - maxValue; 283 | 284 | // Printing the results with two decimal places 285 | System.out.printf("%.2f\n", maxValue); 286 | System.out.printf("%.2f\n", unselectedValue); 287 | 288 | sc.close(); 289 | } 290 | } 291 | 292 | 293 | 294 | // Problem Statement 295 | 296 | // Helen is planning an adventurous journey and needs to pack her knapsack efficiently to make the most out of her limited carrying capacity. 297 | // She has a list of valuable items, each with its weight and value. 298 | 299 | // However, her knapsack can only hold a certain weight. To maximize the total value of her belongings, 300 | // she needs your help to choose the items to include in her knapsack. 301 | 302 | // Implement the 0/1 Knapsack algorithm to determine the optimal selection of items for her knapsack. 303 | 304 | // Input format: 305 | // The first line contains an integer n, representing the total number of items Helen has. 306 | // The next n lines contain two space-separated integers each: val[i] and w[i] denoting the value and weight of the ith item respectively. 307 | // The last line contains an integer W, which represents the maximum weight Helen's knapsack can carry. 308 | 309 | // Output format: 310 | // The output prints "Optimal Total Value: " followed by an integer, representing the optimal total value Helen can obtain by packing her knapsack efficiently. 311 | 312 | // Code constraints: 313 | // 1 ≤ N ≤ 10 314 | // 1 ≤ val[i] ≤ 200 315 | // 1 ≤ w[i] ≤ 50 316 | // 1 ≤ W ≤ 100 317 | 318 | // Sample test cases: 319 | 320 | // Input 1: 321 | // 3 322 | // 60 10 323 | // 100 20 324 | // 120 30 325 | // 50 326 | 327 | // Output 1: 328 | // Optimal Total Value: 220 329 | 330 | // Input 2: 331 | // 4 332 | // 25 5 333 | // 30 8 334 | // 40 10 335 | // 50 15 336 | // 20 337 | 338 | // Output 2: 339 | // Optimal Total Value: 75 340 | 341 | 342 | import java.util.Scanner; 343 | class Knapsack { 344 | 345 | // A utility function that returns maximum of two integers 346 | static int max(int a, int b) { 347 | return (a > b) ? a : b; 348 | } 349 | 350 | // Prints the items which are put in a knapsack of capacity W 351 | static void printKnapSack(int W, int wt[], int val[], int n) { 352 | int i, w; 353 | int[][] K = new int[n + 1][W + 1]; 354 | 355 | // Build table K[][] in bottom up manner 356 | for (i = 0; i <= n; i++) { 357 | for (w = 0; w <= W; w++) { 358 | if (i == 0 || w == 0) 359 | K[i][w] = 0; 360 | else if (wt[i - 1] <= w) 361 | K[i][w] = max(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]); 362 | else 363 | K[i][w] = K[i - 1][w]; 364 | } 365 | } 366 | 367 | // stores the result of Knapsack 368 | int res = K[n][W]; 369 | System.out.printf("Optimal Total Value: %d", res); 370 | } 371 | 372 | public static void main(String[] args) { 373 | Scanner scanner = new Scanner(System.in); 374 | 375 | int n = scanner.nextInt(); 376 | 377 | int[] val = new int[n]; 378 | int[] wt = new int[n]; 379 | 380 | for (int i = 0; i < n; i++) { 381 | val[i] = scanner.nextInt(); 382 | wt[i] = scanner.nextInt(); 383 | } 384 | 385 | int W = scanner.nextInt(); 386 | 387 | printKnapSack(W, wt, val, n); 388 | 389 | scanner.close(); 390 | } 391 | } 392 | 393 | 394 | /* 395 | Problem Statement 396 | 397 | Sam is an adventurous pirate who has recently found a treasure chest on a deserted island. He wants to fill the chest with a selection of treasures, but he can only carry items that fit within the chest's weight limit. Each item has a specific weight and value, and Sam cannot carry fractional items. 398 | 399 | Sam's goal is to select a combination of items that maximizes the total value of the treasures while respecting the chest's weight capacity. Can you help Sam choose the best set of treasures to maximize the value of his loot? 400 | 401 | Example 402 | 403 | Input: 404 | 405 | 3 10 406 | 5 30 407 | 5 40 408 | 5 50 409 | 410 | Output: 411 | 90.00 412 | 413 | Explanation: 414 | Item 1 and Item 2: Total weight = 10, Total value = 30 + 40 = 70. 415 | Item 1 and Item 3: Total weight = 10, Total value = 30 + 50 = 80. 416 | Item 2 and Item 3: Total weight = 10, Total value = 40 + 50 = 90. 417 | The best combination is Item 2 and Item 3, with a total weight of 10 and a total value of 90. 418 | 419 | Input format : 420 | The first line of input consists of two space-separated values an integer N, representing the number of available items, and a double W, representing the maximum weight capacity of the chest. 421 | 422 | The next N lines each contain two space-separated values a double weight[i], representing the weight of the i-th item, and a double value[i], representing the value of the i-th item. 423 | 424 | Output format : 425 | The output prints the double value representing the maximum value that can be packed into the chest, rounded to two decimal places. 426 | 427 | Refer to the sample output for formatting specifications. 428 | 429 | Code constraints : 430 | The given test cases fall under the following specifications: 431 | 432 | 1 ≤ N ≤ 100 433 | 0 < W ≤ 103 434 | 0 < weight[i], value[i] ≤ 103 435 | 436 | Sample test cases : 437 | Input 1 : 438 | 3 10 439 | 5 30 440 | 5 40 441 | 5 50 442 | Output 1 : 443 | 90.00 444 | Input 2 : 445 | 3 20 446 | 5 50 447 | 10 100 448 | 5 60 449 | Output 2 : 450 | 210.00 451 | */ 452 | 453 | 454 | import java.util.*; 455 | 456 | class Item { 457 | double profit, weight; 458 | 459 | Item(double weight, double profit) { 460 | this.weight = weight; 461 | this.profit = profit; 462 | } 463 | } 464 | 465 | class FractionalKnapsack { 466 | 467 | static class ItemComparator implements Comparator { 468 | public int compare(Item a, Item b) { 469 | double r1 = a.profit / a.weight; 470 | double r2 = b.profit / b.weight; 471 | return (r1 > r2) ? -1 : 1; 472 | } 473 | } 474 | 475 | public static double fractionalKnapsack(double W, Item[] arr, int N) { 476 | // Sort items based on the profit/weight ratio 477 | Arrays.sort(arr, new ItemComparator()); 478 | 479 | double finalValue = 0.0; 480 | for (int i = 0; i < N; i++) { 481 | if (arr[i].weight <= W) { 482 | W -= arr[i].weight; 483 | finalValue += arr[i].profit; 484 | } else { 485 | finalValue += arr[i].profit * (W / arr[i].weight); 486 | break; 487 | } 488 | } 489 | 490 | return finalValue; 491 | } 492 | 493 | public static void main(String[] args) { 494 | Scanner sc = new Scanner(System.in); 495 | int N = sc.nextInt(); 496 | double W = sc.nextDouble(); 497 | 498 | Item[] items = new Item[N]; 499 | for (int i = 0; i < N; i++) { 500 | double weight = sc.nextDouble(); 501 | double profit = sc.nextDouble(); 502 | items[i] = new Item(weight, profit); 503 | } 504 | 505 | double maxValue = fractionalKnapsack(W, items, N); 506 | System.out.printf("%.2f\n", maxValue); 507 | } 508 | } 509 | 510 | 511 | 512 | -------------------------------------------------------------------------------- /Lab 3-Greedy&Dynamic Programming/Class Exercise.java: -------------------------------------------------------------------------------- 1 | // Problem Statement 2 | // 3 | // Lorraine is preparing her picnic basket and wants to maximize the value of the items she can carry. 4 | // Each item has a specific weight and value, and She can pack fractional amounts of items to fill her basket optimally. 5 | // 6 | // Your goal is to calculate the total value She can achieve within the basket's weight capacity. 7 | // 8 | // Example 9 | // 10 | // Input: 11 | // 4 10 12 | // 2 3 5 4 13 | // 40 50 100 60 14 | // 15 | // Output: 16 | // 190.00 17 | // 18 | // Explanation: 19 | // 20 | // Calculate the value-to-weight ratios: 21 | // Item 1: 40 / 2 = 20.0, Item 2: 50 / 3 = 16.67, Item 3: 100 / 5 = 20.0, Item 4: 60 / 4 = 15.0 22 | // 23 | // Sort the items by the value-to-weight ratio (descending): 24 | // Item 1: Ratio = 20.0, Item 3: Ratio = 20.0, Item 2: Ratio = 16.67, Item 4: Ratio = 15.0 25 | // 26 | // Fill the knapsack: 27 | // Select Item 3 (weight = 5, value = 100). 28 | // Select Item 2 (weight = 3, value = 50). 29 | // Take 2/4 of Item 4 (value = 60 × 0.5 = 30). 30 | // Total value: 100 + 50 + 30 = 190.00 31 | // 32 | // Input format: 33 | // The first line of the input consists of two integers A and B separated by space, representing the number of items available and the maximum weight capacity of the basket. 34 | // 35 | // The second line of the input consists of space-separated integers, representing the weights of the items. 36 | // 37 | // The third line of the input consists of space-separated integers, representing the values of the items. 38 | // 39 | // Output format: 40 | // The output prints a double, representing the maximum total value, rounded to two decimal places. 41 | // 42 | // Refer to the sample output for formatting specifications. 43 | // 44 | // Code constraints: 45 | // The given test cases fall under the following specifications: 46 | // 47 | // 1 ≤ A ≤ 10, 1 ≤ B ≤ 10, 48 | // 49 | // 1 ≤ weight[i] ≤ 103 50 | // 51 | // 1 ≤ value[i] ≤ 103 52 | // 53 | // Sample test cases: 54 | // Input 1: 55 | // 4 10 56 | // 2 3 5 4 57 | // 40 50 100 60 58 | // Output 1: 59 | // 190.00 60 | // 61 | // Input 2: 62 | // 4 10 63 | // 2 3 4 1 64 | // 10 15 20 5 65 | // Output 2: 66 | // 50.00 67 | 68 | 69 | import java.util.*; 70 | 71 | class FractionalKnapsack { 72 | 73 | static class Item { 74 | int weight; 75 | int value; 76 | double ratio; 77 | int index; 78 | 79 | Item(int weight, int value, int index) { 80 | this.weight = weight; 81 | this.value = value; 82 | this.ratio = (double) value / weight; 83 | this.index = index; 84 | } 85 | } 86 | 87 | // Comparator to sort the items based on their ratio in descending order 88 | static class ItemComparator implements Comparator { 89 | 90 | public int compare(Item a, Item b) { 91 | return Double.compare(b.ratio, a.ratio); // descending order 92 | } 93 | } 94 | 95 | // Function to calculate the maximum value in the fractional knapsack 96 | public static double fractionalKnapsack(int N, int W, int[] weights, int[] values) { 97 | Item[] items = new Item[N]; 98 | for (int i = 0; i < N; i++) { 99 | items[i] = new Item(weights[i], values[i], i + 1); 100 | } 101 | 102 | // Sort items by value-to-weight ratio 103 | Arrays.sort(items, new ItemComparator()); 104 | 105 | double totalValue = 0.0; 106 | int remainingCapacity = W; 107 | 108 | for (int i = 0; i < N; i++) { 109 | if (remainingCapacity == 0) break; 110 | 111 | if (items[i].weight <= remainingCapacity) { 112 | remainingCapacity -= items[i].weight; 113 | totalValue += items[i].value; 114 | } else { 115 | totalValue += items[i].value * ((double) remainingCapacity / items[i].weight); 116 | remainingCapacity = 0; 117 | } 118 | } 119 | 120 | return totalValue; 121 | } 122 | 123 | public static void main(String[] args) { 124 | Scanner sc = new Scanner(System.in); 125 | 126 | // Read the number of items and the capacity of the knapsack 127 | int N = sc.nextInt(); 128 | int W = sc.nextInt(); 129 | 130 | int[] weights = new int[N]; 131 | int[] values = new int[N]; 132 | 133 | // Read the weights of the items 134 | for (int i = 0; i < N; i++) { 135 | weights[i] = sc.nextInt(); 136 | } 137 | 138 | // Read the values of the items 139 | for (int i = 0; i < N; i++) { 140 | values[i] = sc.nextInt(); 141 | } 142 | 143 | // Calculate the maximum value that can be obtained 144 | double maxValue = fractionalKnapsack(N, W, weights, values); 145 | 146 | // Print the result 147 | System.out.printf("%.2f\n", maxValue); 148 | 149 | sc.close(); 150 | } 151 | } 152 | 153 | 154 | 155 | // Problem Statement 156 | // 157 | // Alice wants to solve the fractional knapsack problem using a program. She has a fixed list of 4 items, 158 | // each with a certain value (v) and weight (w). Alice's backpack has a limited weight capacity (W). 159 | // 160 | // The objective is to implement a program that determines the maximum total value of items Alice can carry in her backpack. 161 | // 162 | // Input format: 163 | // The first four lines of input consists of two integers v and w, representing the value and weight of the item separated by space. 164 | // 165 | // The last line consists of an integer W, representing the weight capacity of Alice's backpack. 166 | // 167 | // Output format: 168 | // The first line displays the integers, representing the values of the items, separated by a space. 169 | // 170 | // The second line displays the integer, representing the weights of the items, separated by a space. 171 | // 172 | // The third line shows the float, representing the total weight of items in the backpack, rounded off by two decimal points. 173 | // 174 | // The fourth line displays the float values, representing the maximum value achievable for the given weight capacity, 175 | // rounded off by two decimal points. 176 | // 177 | // Refer to the sample outputs for the exact format. 178 | // 179 | // Code constraints: 180 | // The given test cases fall under the following specifications: 181 | // 182 | // Fixed the 4 items. 183 | // 184 | // 1 ≤ v, w ≤ 1000 185 | // 186 | // 1 ≤ W ≤ 100 187 | // 188 | // Sample test cases: 189 | // 190 | // Input 1: 191 | // 300 6 192 | // 150 3 193 | // 120 3 194 | // 100 2 195 | // 10 196 | // 197 | // Output 1: 198 | // Values: 300 150 120 100 199 | // Weights: 6 3 3 2 200 | // Total weight in bag: 10.00 201 | // Max value for 10 weight is 500.00 202 | // 203 | // Input 2: 204 | // 100 10 205 | // 280 40 206 | // 120 20 207 | // 120 24 208 | // 60 209 | // 210 | // Output 2: 211 | // Values: 100 280 120 120 212 | // Weights: 10 40 20 24 213 | // Total weight in bag: 60.00 214 | // Max value for 60 weight is 440.00 215 | 216 | 217 | 218 | import java.util.Scanner; 219 | 220 | class Item { 221 | int v; // Value of the item 222 | int w; // Weight of the item 223 | float d; // Value-to-weight ratio (v/w) 224 | 225 | Item(int v, int w) { 226 | this.v = v; 227 | this.w = w; 228 | this.d = (float) v / w; // Calculate value-to-weight ratio 229 | } 230 | } 231 | 232 | class FractionalKnapsack { 233 | 234 | public static void input(Item[] items) { 235 | Scanner sc = new Scanner(System.in); 236 | for (int i = 0; i < items.length; i++) { 237 | items[i].v = sc.nextInt(); 238 | items[i].w = sc.nextInt(); 239 | items[i].d = (float) items[i].v / items[i].w; // Calculate ratio for sorting 240 | } 241 | } 242 | 243 | public static void display(Item[] items) { 244 | System.out.print("Values: "); 245 | for (Item item : items) { 246 | System.out.print(item.v + " "); 247 | } 248 | System.out.println(); 249 | 250 | System.out.print("Weights: "); 251 | for (Item item : items) { 252 | System.out.print(item.w + " "); 253 | } 254 | System.out.println(); 255 | } 256 | 257 | // Sort the items based on value-to-weight ratio in descending order 258 | public static void bubbleSort(Item[] items) { 259 | for (int i = 0; i < items.length - 1; i++) { 260 | for (int j = 0; j < items.length - i - 1; j++) { 261 | if (items[j].d < items[j + 1].d) { 262 | Item temp = items[j]; 263 | items[j] = items[j + 1]; 264 | items[j + 1] = temp; 265 | } 266 | } 267 | } 268 | } 269 | 270 | public static float knapsack(Item[] items, int W) { 271 | float totalValue = 0, totalWeight = 0; 272 | 273 | // Sort items by value-to-weight ratio in descending order 274 | bubbleSort(items); 275 | 276 | // Select items based on sorted order 277 | for (Item item : items) { 278 | if (totalWeight + item.w <= W) { 279 | totalValue += item.v; 280 | totalWeight += item.w; 281 | } else { 282 | int remainingWeight = W - (int) totalWeight; 283 | totalValue += remainingWeight * item.d; // Add fraction of the item 284 | totalWeight += remainingWeight; 285 | break; // The bag is full 286 | } 287 | } 288 | 289 | return totalValue; 290 | } 291 | 292 | public static void main(String[] args) { 293 | Scanner sc = new Scanner(System.in); 294 | Item[] items = new Item[4]; 295 | 296 | // Input the item values and weights 297 | for (int i = 0; i < 4; i++) { 298 | items[i] = new Item(sc.nextInt(), sc.nextInt()); 299 | } 300 | 301 | // Display item values and weights 302 | display(items); 303 | 304 | // Input the maximum weight of the backpack 305 | int W = sc.nextInt(); 306 | 307 | // Calculate the maximum value that can be obtained with the given weight 308 | float maxValue = knapsack(items, W); 309 | 310 | // Calculate the total weight of items in the knapsack 311 | float totalWeight = 0; 312 | for (Item item : items) { 313 | if (totalWeight + item.w <= W) { 314 | totalWeight += item.w; 315 | } else { 316 | int remainingWeight = W - (int) totalWeight; 317 | totalWeight += remainingWeight; 318 | break; 319 | } 320 | } 321 | 322 | // Output the total weight and maximum value rounded to 2 decimal places 323 | System.out.printf("Total weight in bag: %.2f\n", totalWeight); 324 | System.out.printf("Max value for %d weight is %.2f\n", W, maxValue); 325 | } 326 | } 327 | 328 | 329 | -------------------------------------------------------------------------------- /Lab 3-Greedy&Dynamic Programming/Practice At Home.java: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Statement 3 | 4 | Reni, an avid traveler, is preparing for her next adventure. She's limited by the amount of weight she can carry in her backpack, but she wants to maximize the value of the items she brings along. Reni knows the value and weight of each item she's considering, and she needs your help to determine which items to pack. 5 | 6 | You're tasked with implementing a solution to the 0/1 knapsack problem to assist Reni in selecting the most valuable combination of items without exceeding her backpack's weight limit. 7 | 8 | Input format: 9 | The first line of input contains an integer, n, representing the number of items Reni has. 10 | The second line contains n space-separated integers val[i], representing the values of the items. 11 | The third line contains n space-separated integers w[i], representing the weights of the items. 12 | The fourth line contains an integer W, indicating the maximum weight Reni's backpack can hold. 13 | 14 | Output format: 15 | The output displays the "Specified weights: " followed by a space-separated list of integers representing the weights of the items that Reni should pack in her backpack to maximize the total value. 16 | 17 | Code constraints: 18 | In this scenario, the test cases fall under the following constraints: 19 | 1 ≤ N ≤ 10 20 | 1 ≤ Val[i] ≤ 100 21 | 1 ≤ w[i] ≤ 50 22 | 1 ≤ W ≤ 100 23 | 24 | Sample test cases: 25 | Input 1: 26 | 4 27 | 10 20 30 40 28 | 1 2 3 4 29 | 8 30 | Output 1: 31 | Specified weights: 4 3 1 32 | 33 | Input 2: 34 | 5 35 | 2 3 4 5 6 36 | 5 6 8 10 12 37 | 7 38 | Output 2: 39 | Specified weights: 6 40 | */ 41 | 42 | 43 | import java.util.Scanner; 44 | 45 | class Knapsack { 46 | 47 | public static int max(int a, int b) { 48 | return (a > b) ? a : b; 49 | } 50 | 51 | public static void printknapSack(int W, int[] wt, int[] val, int n) { 52 | int i, w; 53 | int[][] K = new int[n + 1][W + 1]; 54 | 55 | for (i = 0; i <= n; i++) { 56 | for (w = 0; w <= W; w++) { 57 | if (i == 0 || w == 0) 58 | K[i][w] = 0; 59 | else if (wt[i - 1] <= w) 60 | K[i][w] = max(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]); 61 | else 62 | K[i][w] = K[i - 1][w]; 63 | } 64 | } 65 | 66 | w = W; 67 | System.out.print("Specified weights: "); 68 | for (i = n; i > 0 && K[i][w] > 0; i--) { 69 | if (K[i][w] == K[i - 1][w]) 70 | continue; 71 | else { 72 | System.out.print(wt[i - 1] + " "); 73 | w = w - wt[i - 1]; 74 | } 75 | } 76 | } 77 | 78 | public static void main(String[] args) { 79 | Scanner sc = new Scanner(System.in); 80 | int[] val = new int[100]; 81 | int[] wt = new int[100]; 82 | int W, n; 83 | 84 | n = sc.nextInt(); 85 | 86 | for (int i = 0; i < n; i++) 87 | val[i] = sc.nextInt(); 88 | 89 | for (int i = 0; i < n; i++) 90 | wt[i] = sc.nextInt(); 91 | 92 | W = sc.nextInt(); 93 | 94 | printknapSack(W, wt, val, n); 95 | 96 | sc.close(); 97 | } 98 | } 99 | 100 | /* 101 | Problem Statement 102 | 103 | Sarah loves challenges and has recently taken up a new programming problem. She is fascinated by the classic "0/1 Knapsack Problem" and wants to create a program that can efficiently solve it. 104 | 105 | The 0/1 Knapsack Problem involves selecting a combination of items with given weights and values to maximize the total value, while not exceeding a given weight capacity. 106 | 107 | Write a program that takes input for the 0/1 Knapsack Problem and outputs the maximum value that can be achieved, as well as the selected weights that contribute to this maximum value. 108 | 109 | Input format: 110 | The first line contains an integer n, representing the number of items available. 111 | The second line contains n integers separated by space, representing the values of the items. The ith integer corresponds to the value of the ith item. 112 | The third line contains n integers separated by space, representing the weights of the items. The ith integer corresponds to the weight of the ith item. 113 | The fourth line contains an integer W, representing the maximum weight capacity of the knapsack. 114 | 115 | Output format: 116 | The first line output displays "Maximum value: " followed by an integer, representing the maximum value that can be achieved. 117 | The second line output displays "Selected weights: " followed by space-separated integers, representing the selected weights contributing to the maximum value. 118 | 119 | Code constraints: 120 | In this scenario, the test cases fall under the following constraints: 121 | 1 ≤ n ≤ 10 122 | 1 ≤ val[i] ≤ 100 123 | 1 ≤ wt[i] ≤ 100 124 | 1 ≤ W ≤ 1000 125 | 126 | Sample test cases: 127 | Input 1: 128 | 3 129 | 60 100 120 130 | 10 20 30 131 | 50 132 | Output 1: 133 | Maximum value: 220 134 | Selected weights: 30 20 135 | 136 | Input 2: 137 | 4 138 | 10 20 30 40 139 | 1 2 3 4 140 | 8 141 | Output 2: 142 | Maximum value: 80 143 | Selected weights: 4 3 1 144 | */ 145 | 146 | 147 | import java.util.Scanner; 148 | 149 | class Knapsack01 { 150 | 151 | // Function to find the maximum of two integers 152 | private static int max(int a, int b) { 153 | return (a > b) ? a : b; 154 | } 155 | 156 | // Function to solve the 0/1 Knapsack problem and print the results 157 | private static void printknapSack(int W, int[] wt, int[] val, int n) { 158 | int[][] K = new int[n + 1][W + 1]; 159 | 160 | // Build the DP table in bottom up manner 161 | for (int i = 0; i <= n; i++) { 162 | for (int w = 0; w <= W; w++) { 163 | if (i == 0 || w == 0) 164 | K[i][w] = 0; 165 | else if (wt[i - 1] <= w) 166 | K[i][w] = max(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]); 167 | else 168 | K[i][w] = K[i - 1][w]; 169 | } 170 | } 171 | 172 | // Store the result of the knapsack 173 | int res = K[n][W]; 174 | System.out.println("Maximum value: " + res); 175 | 176 | // Trace the selected weights 177 | int w = W; 178 | System.out.print("Selected weights: "); 179 | for (int i = n; i > 0 && res > 0; i--) { 180 | if (res != K[i - 1][w]) { // This item is included. 181 | System.out.print(wt[i - 1] + " "); 182 | res = res - val[i - 1]; // Reduce res by the value of this item 183 | w = w - wt[i - 1]; // Reduce w by the weight of this item 184 | } 185 | } 186 | } 187 | 188 | public static void main(String[] args) { 189 | Scanner scanner = new Scanner(System.in); 190 | 191 | int n = scanner.nextInt(); 192 | int[] val = new int[n]; 193 | int[] wt = new int[n]; 194 | 195 | // Read values 196 | for (int i = 0; i < n; i++) { 197 | val[i] = scanner.nextInt(); 198 | } 199 | 200 | // Read weights 201 | for (int i = 0; i < n; i++) { 202 | wt[i] = scanner.nextInt(); 203 | } 204 | 205 | // Read the maximum weight capacity 206 | int W = scanner.nextInt(); 207 | 208 | // Solve the knapsack problem 209 | printknapSack(W, wt, val, n); 210 | 211 | scanner.close(); 212 | } 213 | } 214 | 215 | /* 216 | Problem Statement 217 | 218 | Liam is packing goods onto his cargo ship, and he wants to maximize the total value of the items he can transport, subject to the ship's weight capacity. However, he can carry only fractions of items, and the value and weight of each item are provided. Sort the items by the value-to-weight ratio in descending order. 219 | 220 | Help Liam to determine the maximum value of goods he can pack and list the selected items along with the fractions of each item taken. 221 | 222 | Example 223 | 224 | Input: 225 | 3 30 226 | 10 100 227 | 15 180 228 | 20 240 229 | 230 | Output: 231 | 2 1.00 232 | 3 0.75 233 | 360.00 234 | 235 | Explanation: 236 | 237 | Sort items by value-to-weight ratio: 238 | Item 1: (weight = 10, value = 100) → value-to-weight ratio = 100 / 10 = 10.0 239 | Item 2: (weight = 15, value = 180) → value-to-weight ratio = 180 / 15 = 12.0 240 | Item 3: (weight = 20, value = 240) → value-to-weight ratio = 240 / 20 = 12.0 241 | 242 | Sorted by value-to-weight ratio: 243 | Item 2 (12.0) 244 | Item 3 (12.0) 245 | Item 1 (10.0) 246 | 247 | Greedy selection: 248 | Item 2 (weight = 15, value = 180): Fully added. Remaining capacity = 30 - 15 = 15. 249 | Item 3 (weight = 20, value = 240): Can only take 15 units (fraction). Remaining capacity = 15. 250 | Fraction taken: 15 / 20 = 0.75. 251 | Value added: 240 * 0.75 = 180. 252 | 253 | Total value: 254 | Item 2: 180 (fully taken) 255 | Item 3: 180 (fraction taken) 256 | Total = 180 + 180 = 360.00 257 | 258 | Input format: 259 | The first line of the input contains two space-separated values: 260 | N (integer) — the number of goods. 261 | W (double) — the ship's weight capacity. 262 | 263 | The next N lines of the input each contain two space-separated values: 264 | weight[i] (double) — the weight of the ith good. 265 | value[i] (double) — the value of the ith good. 266 | 267 | Output format: 268 | The first M Lines of output prints i, fraction separated by a space, where i is the 1-based index of the item and fraction is the fraction of the item taken. 269 | The last line of output prints the maximum value of goods, rounded to two decimal places. 270 | 271 | Code constraints: 272 | The given test cases fall under the following constraints: 273 | 1 ≤ N ≤ 15 274 | 1 ≤ value[i], weight[i] ≤ 1000 275 | 1 ≤ W ≤ 1000 276 | 277 | Sample test cases: 278 | Input 1: 279 | 4 50 280 | 10 200 281 | 20 300 282 | 30 150 283 | 40 100 284 | 285 | Output 1: 286 | 1 1.00 287 | 2 1.00 288 | 3 0.67 289 | 600.00 290 | 291 | Input 2: 292 | 3 30 293 | 10 100 294 | 15 180 295 | 20 240 296 | 297 | Output 2: 298 | 2 1.00 299 | 3 0.75 300 | 360.00 301 | */ 302 | 303 | 304 | import java.util.*; 305 | 306 | class Item { 307 | double weight; 308 | double value; 309 | double valuePerWeight; 310 | int index; 311 | 312 | public Item(int index, double weight, double value) { 313 | this.index = index; 314 | this.weight = weight; 315 | this.value = value; 316 | this.valuePerWeight = value / weight; 317 | } 318 | } 319 | 320 | class FractionalKnapsack { 321 | 322 | public static void main(String[] args) { 323 | Scanner sc = new Scanner(System.in); 324 | 325 | int n = sc.nextInt(); // Number of goods 326 | double W = sc.nextDouble(); // Ship's weight capacity 327 | 328 | Item[] items = new Item[n]; 329 | 330 | // Input the items (weight, value) and store them in the items array 331 | for (int i = 0; i < n; i++) { 332 | double weight = sc.nextDouble(); 333 | double value = sc.nextDouble(); 334 | items[i] = new Item(i + 1, weight, value); 335 | } 336 | 337 | // Sort items based on value-to-weight ratio in descending order 338 | Arrays.sort(items, (a, b) -> Double.compare(b.valuePerWeight, a.valuePerWeight)); 339 | 340 | double totalValue = 0.0; 341 | double remainingWeight = W; 342 | 343 | // Greedy selection of items based on sorted value-to-weight ratio 344 | for (int i = 0; i < n; i++) { 345 | if (remainingWeight <= 0) break; 346 | 347 | if (items[i].weight <= remainingWeight) { 348 | // Fully take the item 349 | remainingWeight -= items[i].weight; 350 | totalValue += items[i].value; 351 | System.out.println(items[i].index + " 1.00"); 352 | } else { 353 | // Take the fraction of the item 354 | double fraction = remainingWeight / items[i].weight; 355 | totalValue += items[i].value * fraction; 356 | System.out.printf("%d %.2f\n", items[i].index, fraction); 357 | remainingWeight = 0; // All capacity is used 358 | } 359 | } 360 | 361 | // Output the total value of the selected goods, rounded to two decimal places 362 | System.out.printf("%.2f\n", totalValue); 363 | 364 | sc.close(); 365 | } 366 | } 367 | 368 | 369 | /* 370 | Problem Statement 371 | 372 | You are given a set of items, each with a specific weight and value. Your task is to determine the maximum value that can be obtained by selecting a combination of these items, considering a knapsack with a limited capacity. You are allowed to take fractions of items into the knapsack. 373 | 374 | Write a program to implement the fractional knapsack problem. 375 | 376 | Input format: 377 | The input consists of several lines, each representing an item. 378 | Each item is represented by two integers separated by a space: the weight of the item followed by its value. 379 | The input terminates with a line containing a single integer -1. 380 | After the items, there is an integer representing the maximum weight capacity. 381 | 382 | Output format: 383 | The output prints "The maximum value of the current list is: ", followed by a double value, representing the maximum value that can be obtained by selecting fractions of items to fit into the knapsack, rounded off to two decimal points. 384 | 385 | Refer to the sample outputs for the exact format. 386 | 387 | Code constraints: 388 | The given test cases fall under the following specifications: 389 | 1 ≤ weight and values ≤ 1000 390 | 1 ≤ capacity ≤ 100 391 | 392 | Sample test cases: 393 | Input 1: 394 | 10 60 395 | 20 100 396 | 30 120 397 | -1 398 | 50 399 | 400 | Output 1: 401 | The maximum value of the current list is: 402 | 240.00 403 | 404 | Input 2: 405 | 10 100 406 | 40 280 407 | 20 120 408 | 24 120 409 | -1 410 | 60 411 | 412 | Output 2: 413 | The maximum value of the current list is: 414 | 440.00 415 | */ 416 | 417 | 418 | 419 | import java.util.Scanner; 420 | 421 | class Item { 422 | int weight; 423 | int value; 424 | 425 | Item(int weight, int value) { 426 | this.weight = weight; 427 | this.value = value; 428 | } 429 | } 430 | 431 | class FractionalKnapsack { 432 | 433 | // Function to swap two items 434 | public static void swap(Item[] items, int i, int j) { 435 | Item temp = items[i]; 436 | items[i] = items[j]; 437 | items[j] = temp; 438 | } 439 | 440 | // Function to sort items by value-to-weight ratio 441 | public static void sortByRatio(Item[] items, int n) { 442 | for (int i = 0; i < n - 1; i++) { 443 | for (int j = 0; j < n - i - 1; j++) { 444 | double ratio1 = (double) items[j].value / items[j].weight; 445 | double ratio2 = (double) items[j + 1].value / items[j + 1].weight; 446 | if (ratio1 < ratio2) { 447 | swap(items, j, j + 1); 448 | } 449 | } 450 | } 451 | } 452 | 453 | // Function to solve the fractional knapsack problem 454 | public static double fractionalKnapsack(Item[] items, int n, int capacity) { 455 | double totalValue = 0.0; 456 | 457 | sortByRatio(items, n); 458 | 459 | for (int i = 0; i < n; i++) { 460 | if (capacity == 0) 461 | break; 462 | 463 | if (items[i].weight <= capacity) { 464 | totalValue += items[i].value; 465 | capacity -= items[i].weight; 466 | } else { 467 | totalValue += (double) items[i].value * capacity / items[i].weight; 468 | capacity = 0; 469 | } 470 | } 471 | 472 | return totalValue; 473 | } 474 | 475 | public static void main(String[] args) { 476 | Scanner scanner = new Scanner(System.in); 477 | Item[] items = new Item[1000]; 478 | int n = 0; 479 | 480 | while (true) { 481 | int weight = scanner.nextInt(); 482 | if (weight == -1) 483 | break; 484 | int value = scanner.nextInt(); 485 | items[n] = new Item(weight, value); 486 | n++; 487 | } 488 | 489 | int capacity = scanner.nextInt(); 490 | 491 | double maxValue = fractionalKnapsack(items, n, capacity); 492 | 493 | System.out.println("The maximum value of the current list is:"); 494 | System.out.printf("%.2f", maxValue); 495 | 496 | scanner.close(); 497 | } 498 | } 499 | 500 | -------------------------------------------------------------------------------- /Lab 4 - Optimal Ordering/Challenge Yourself.java: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Statement 3 | 4 | Liam is simulating complex weather patterns using matrices. His simulation requires efficient matrix multiplications to optimize performance. Given a sequence of matrix dimensions, he wants to determine the minimum number of scalar multiplications required to multiply them in the most efficient order. 5 | 6 | To further optimize computation: 7 | 8 | If n ≥ 3, always prioritize splitting the multiplication at the middle matrix first. 9 | Use dynamic programming and recursion to find the optimal order of multiplication. 10 | Finally, determine and print the minimum cost and the initial optimal split position. 11 | 12 | Input format: 13 | The first line contains a single integer n, representing the number of dimensions in the array. 14 | The second line contains n integers, representing the dimensions of the matrices. 15 | 16 | Output format: 17 | The output prints an integer representing the minimum number of scalar multiplications required. 18 | The second line prints "Optimal computation starts with a split at matrix X (dimensions: A x B) where X is the index of the splitting matrix, A is its row count, and B is its column count. 19 | 20 | Refer to the sample output for formatting specifications. 21 | 22 | Code constraints: 23 | The given test cases fall under the following specifications: 24 | 3 ≤ n ≤ 100 25 | 1 ≤ dimensions of matrices ≤ 500 26 | 27 | Sample test cases: 28 | Input 1: 29 | 5 30 | 1 2 3 4 3 31 | 32 | Output 1: 33 | 30 34 | Optimal computation starts with a split at matrix 2 (dimensions: 3 x 4). 35 | 36 | Input 2: 37 | 3 38 | 10 20 30 39 | 40 | Output 2: 41 | 6000 42 | Optimal computation starts with a split at matrix 1 (dimensions: 20 x 30). 43 | */ 44 | 45 | 46 | import java.util.Scanner; 47 | 48 | class MatrixChainMultiplication { 49 | 50 | // Function to find the middle index for a chain 51 | public static int findMiddleIndex(int start, int end) { 52 | return (start + end) / 2; 53 | } 54 | 55 | // Function to compute the minimum multiplications cost recursively 56 | public static int minMultiplications(int[] arr, int i, int j, int[][] dp, boolean useMiddle) { 57 | // Base case: If there's only one matrix, no multiplication is needed 58 | if (i + 1 == j) { 59 | return 0; 60 | } 61 | 62 | // If the result is already computed, return it 63 | if (dp[i][j] != -1) { 64 | return dp[i][j]; 65 | } 66 | 67 | int minCost = Integer.MAX_VALUE; 68 | 69 | // Prioritize middle index split if useMiddle flag is set 70 | if (useMiddle) { 71 | int mid = findMiddleIndex(i, j); 72 | if (mid > i && mid < j) { // Ensure mid is a valid split 73 | int cost = minMultiplications(arr, i, mid, dp, false) + 74 | minMultiplications(arr, mid, j, dp, false) + 75 | arr[i] * arr[mid] * arr[j]; 76 | 77 | if (cost < minCost) { 78 | minCost = cost; 79 | } 80 | } 81 | } 82 | 83 | // Try all possible partitions to find the minimum cost 84 | for (int k = i + 1; k < j; k++) { 85 | int cost = minMultiplications(arr, i, k, dp, false) + 86 | minMultiplications(arr, k, j, dp, false) + 87 | arr[i] * arr[k] * arr[j]; 88 | 89 | if (cost < minCost) { 90 | minCost = cost; 91 | } 92 | } 93 | 94 | dp[i][j] = minCost; // Store the computed result in dp table 95 | return minCost; 96 | } 97 | 98 | // Function to compute the minimum cost of matrix chain multiplication 99 | public static int matrixChainMultiplication(int[] arr, int n) { 100 | int[][] dp = new int[100][100]; 101 | 102 | // Initialize dp table with -1 103 | for (int i = 0; i < n; i++) { 104 | for (int j = 0; j < n; j++) { 105 | dp[i][j] = -1; 106 | } 107 | } 108 | 109 | // Call the recursive function to compute the minimum cost 110 | return minMultiplications(arr, 0, n - 1, dp, true); 111 | } 112 | 113 | public static void main(String[] args) { 114 | Scanner sc = new Scanner(System.in); 115 | 116 | // Input the number of matrices (n) 117 | int n = sc.nextInt(); 118 | 119 | // Input the dimensions of matrices (this should be n+1 elements) 120 | int[] arr = new int[n]; 121 | for (int i = 0; i < n; i++) { 122 | arr[i] = sc.nextInt(); 123 | } 124 | 125 | // Compute the minimum cost of matrix chain multiplication 126 | int result = matrixChainMultiplication(arr, n); 127 | 128 | // Print the result 129 | System.out.println(result); 130 | 131 | // Find the middle index for the first split 132 | int mid = findMiddleIndex(0, n - 1); 133 | 134 | // Print the optimal split information 135 | if (mid + 1 < n) { 136 | System.out.printf("Optimal computation starts with a split at matrix %d (dimensions: %d x %d).\n", 137 | mid, arr[mid], arr[mid + 1]); 138 | } else { 139 | System.out.printf("Optimal computation starts with a split at matrix %d.\n", mid); 140 | } 141 | 142 | sc.close(); 143 | } 144 | } 145 | 146 | 147 | 148 | /* 149 | Problem Statement 150 | 151 | Raj is optimizing the computation of a machine learning model where each layer is represented by a matrix. To reduce computational costs and improve performance, he needs to avoid splitting matrices with large dimensions early in the computation process. 152 | 153 | Instead, he aims to defer splitting on the matrix with the largest dimension until all other dimensions have been considered. 154 | 155 | Input format: 156 | The first line contains a single integer n, representing the number of dimensions in the array. 157 | The second line contains n integers, p[0], p[1], ..., p[n-1], where p[i] represents the dimensions of the matrices. 158 | 159 | Output format: 160 | The output prints a single integer representing the minimum number of scalar multiplications required to compute the product of the matrices in the optimal order. 161 | 162 | Code constraints: 163 | The given test cases fall under the following specifications: 164 | 3 ≤ n ≤ 100 165 | 1 ≤ p[i] ≤ 500 166 | 167 | Sample test cases: 168 | Input 1: 169 | 5 170 | 1 2 3 4 3 171 | 172 | Output 1: 173 | 51 174 | 175 | Input 2: 176 | 3 177 | 10 20 30 178 | 179 | Output 2: 180 | 6000 181 | */ 182 | 183 | 184 | import java.util.Scanner; 185 | 186 | class MatrixChainMultiplication { 187 | 188 | // Function to find the index of the largest dimension in the range (start, end) 189 | public static int findLargestDimension(int[] arr, int start, int end) { 190 | int maxIndex = start; 191 | for (int i = start + 1; i < end; i++) { 192 | if (arr[i] > arr[maxIndex]) { 193 | maxIndex = i; 194 | } 195 | } 196 | return maxIndex; 197 | } 198 | 199 | // Function to compute the minimum multiplication cost for matrix chain multiplication 200 | public static int matrixChainMultiplication(int[] arr, int n) { 201 | int[][] dp = new int[n][n]; 202 | 203 | // Initialize the DP table 204 | for (int i = 0; i < n; i++) { 205 | for (int j = 0; j < n; j++) { 206 | dp[i][j] = 0; 207 | } 208 | } 209 | 210 | // Compute the minimum cost for different chain lengths 211 | for (int length = 2; length < n; length++) { 212 | for (int i = 0; i < n - length; i++) { 213 | int j = i + length; 214 | dp[i][j] = Integer.MAX_VALUE; 215 | 216 | // Find the largest dimension index in the current range 217 | int largestDimIndex = findLargestDimension(arr, i + 1, j); 218 | 219 | // Try all possible splits and calculate the cost 220 | for (int k = i + 1; k < j; k++) { 221 | if (k == largestDimIndex && j - i > 2) { 222 | continue; // Skip if we encounter the largest dimension for a longer chain 223 | } 224 | int cost = dp[i][k] + dp[k][j] + arr[i] * arr[k] * arr[j]; 225 | if (cost < dp[i][j]) { 226 | dp[i][j] = cost; 227 | } 228 | } 229 | } 230 | } 231 | 232 | return dp[0][n - 1]; // Return the minimum multiplication cost for the entire chain 233 | } 234 | 235 | public static void main(String[] args) { 236 | Scanner sc = new Scanner(System.in); 237 | 238 | // Input the number of matrices (n) 239 | int n = Integer.parseInt(sc.nextLine().trim()); // Read n as a string and parse it 240 | 241 | // Input the dimensions of matrices (this should be n+1 elements) 242 | String[] input = sc.nextLine().trim().split(" "); 243 | int[] arr = new int[n]; 244 | for (int i = 0; i < n; i++) { 245 | arr[i] = Integer.parseInt(input[i]); // Parse the array of dimensions 246 | } 247 | 248 | // Compute the minimum cost of matrix chain multiplication 249 | int result = matrixChainMultiplication(arr, n); 250 | 251 | // Output the result 252 | System.out.println(result); 253 | 254 | sc.close(); 255 | } 256 | } 257 | 258 | 259 | /* 260 | Problem Statement 261 | 262 | A computing system needs to process multiple matrix multiplications as part of a data analysis pipeline. Since matrix multiplication is computationally expensive, the system must determine the most efficient order to multiply the matrices to minimize the total number of scalar multiplications. 263 | 264 | You are given a sequence of matrices, where each matrix Mi has dimensions pi−1×pi​. Given an array of dimensions dims of size n+1, where the ith matrix Mi has dimensions dims[i-1] × dims[i], determine the optimal way to multiply the matrices with the minimum number of scalar multiplications. 265 | 266 | Your task is to compute and print the minimum number of scalar multiplications required for efficient computation. 267 | 268 | Input format: 269 | The first line of input consists of a single number n representing the number of matrices. 270 | The second line of input consists of n + 1 integers representing the dimensions of the matrices separated by spaces. 271 | 272 | Output format: 273 | The output prints the minimum number of scalar multiplications required. 274 | 275 | Code constraints: 276 | The given test cases fall under the following specifications: 277 | 1 ≤ n ≤ 100 278 | 279 | Sample test cases: 280 | Input 1: 281 | 2 282 | 10 20 30 283 | 284 | Output 1: 285 | Minimum number of multiplications is: 6000 286 | 287 | Input 2: 288 | 4 289 | 10 50 20 30 40 290 | 291 | Output 2: 292 | Minimum number of multiplications is: 28000 293 | */ 294 | 295 | 296 | import java.util.Scanner; 297 | 298 | class MatrixChainMultiplication { 299 | 300 | // Function to compute the minimum cost of matrix chain multiplication 301 | public static int matrixChainOrder(int[] dims, int n) { 302 | final int MAX = 201; // Maximum number of matrices 303 | int[][] dp = new int[MAX][MAX]; // DP table to store minimum cost 304 | int[][] split = new int[MAX][MAX]; // Table to store the split position 305 | 306 | // Initialize the dp table with 0 for single matrices 307 | for (int i = 0; i < n; i++) { 308 | dp[i][i] = 0; 309 | } 310 | 311 | // Cost for chains of length 2 to n 312 | for (int len = 2; len <= n; len++) { // Chain length 313 | for (int i = 0; i < n - len + 1; i++) { // Starting index of the chain 314 | int j = i + len - 1; // Ending index of the chain 315 | dp[i][j] = Integer.MAX_VALUE; // Set the cost to maximum initially 316 | 317 | // Try all possible splits to find the minimum cost 318 | for (int k = i; k < j; k++) { 319 | int q = dp[i][k] + dp[k + 1][j] + dims[i] * dims[k + 1] * dims[j + 1]; 320 | if (q < dp[i][j]) { 321 | dp[i][j] = q; 322 | split[i][j] = k; // Record the split position 323 | } 324 | } 325 | } 326 | } 327 | 328 | // Return the minimum cost for multiplying matrices from 1 to n 329 | return dp[0][n - 1]; 330 | } 331 | 332 | public static void main(String[] args) { 333 | Scanner sc = new Scanner(System.in); 334 | 335 | // Input number of matrices 336 | int n = sc.nextInt(); 337 | 338 | // Input the dimensions of matrices 339 | int[] dims = new int[n + 1]; 340 | for (int i = 0; i <= n; i++) { 341 | dims[i] = sc.nextInt(); 342 | } 343 | 344 | // Compute the minimum cost 345 | int minCost = matrixChainOrder(dims, n); 346 | System.out.println("Minimum number of multiplications is: " + minCost); 347 | 348 | sc.close(); 349 | } 350 | } 351 | 352 | 353 | 354 | /* 355 | Problem Statement: 356 | 357 | Jake is a data scientist working for a large e-commerce company that processes a series of data matrices representing sales data from different regions. Each matrix corresponds to sales data for a specific region and has dimensions that represent the number of products and the number of time periods. 358 | 359 | The company needs to combine these matrices to analyze overall sales trends, but the order in which the matrices are combined affects the computational efficiency. Help Jake determine the most efficient way to multiply a chain of matrices to minimize the total computational cost. Compute the minimum number of scalar multiplications needed to multiply the chain of matrices and the optimal parenthesization of the matrices. 360 | 361 | Input format: 362 | - The first line of input consists of a single integer n, which represents the number of matrices in the chain. 363 | - The second line of input consists of (n + 1) integers, which represent the dimensions of the matrices in the chain. The first integer indicates the number of rows in the first matrix, and each subsequent integer indicates the number of columns in the corresponding matrix, with the last integer representing the number of columns in the last matrix. 364 | 365 | Output format: 366 | - The output prints the Optimal Parenthesization and the Minimum number of multiplications. 367 | 368 | Code constraints: 369 | The given test cases fall under the following specifications: 370 | 1 ≤ n ≤ 100 371 | 372 | Sample test cases: 373 | Input 1: 374 | 4 375 | 5 10 20 15 30 376 | 377 | Output 1: 378 | Optimal Parenthesization: (((A1A2)A3)A4) 379 | Minimum number of multiplications is: 4750 380 | 381 | Input 2: 382 | 2 383 | 10 20 30 384 | 385 | Output 2: 386 | Optimal Parenthesization: (A1A2) 387 | Minimum number of multiplications is: 6000 388 | */ 389 | 390 | 391 | import java.util.Scanner; 392 | 393 | class MatrixChainMultiplication { 394 | 395 | // Function to print the optimal parenthesization 396 | public static void printOptimalParenthesization(int[][] split, int i, int j) { 397 | if (i == j) { 398 | System.out.print("A" + (i + 1)); // Print matrix name (A1, A2, ...) 399 | } else { 400 | System.out.print("("); 401 | printOptimalParenthesization(split, i, split[i][j]); 402 | printOptimalParenthesization(split, split[i][j] + 1, j); 403 | System.out.print(")"); 404 | } 405 | } 406 | 407 | // Function to compute minimum cost of matrix chain multiplication 408 | public static int matrixChainOrder(int[] dims, int n) { 409 | int[][] dp = new int[100][100]; // DP table to store minimum cost 410 | int[][] split = new int[100][100]; // Table to store the split position 411 | 412 | // Cost for chains of length 2 to n 413 | for (int len = 2; len <= n; ++len) { // Chain length 414 | for (int i = 0; i < n - len + 1; ++i) { // Starting index of the chain 415 | int j = i + len - 1; // Ending index of the chain 416 | dp[i][j] = Integer.MAX_VALUE; // Set the cost to maximum initially 417 | 418 | // Try all possible splits to find the minimum cost 419 | for (int k = i; k < j; ++k) { 420 | int q = dp[i][k] + dp[k + 1][j] + dims[i] * dims[k + 1] * dims[j + 1]; 421 | if (q < dp[i][j]) { 422 | dp[i][j] = q; 423 | split[i][j] = k; // Record the split position 424 | } 425 | } 426 | } 427 | } 428 | 429 | // Print the optimal parenthesization 430 | System.out.print("Optimal Parenthesization: "); 431 | printOptimalParenthesization(split, 0, n - 1); 432 | System.out.println(); 433 | 434 | // Return the minimum cost for multiplying matrices from 1 to n 435 | return dp[0][n - 1]; 436 | } 437 | 438 | public static void main(String[] args) { 439 | Scanner sc = new Scanner(System.in); 440 | 441 | // Input number of matrices 442 | int n = sc.nextInt(); 443 | 444 | // Input the dimensions of matrices 445 | int[] dims = new int[n + 1]; 446 | for (int i = 0; i <= n; ++i) { 447 | dims[i] = sc.nextInt(); 448 | } 449 | 450 | // Compute the minimum cost 451 | int minCost = matrixChainOrder(dims, n); 452 | System.out.println("Minimum number of multiplications is: " + minCost); 453 | 454 | sc.close(); 455 | } 456 | } 457 | 458 | 459 | 460 | -------------------------------------------------------------------------------- /Lab 4 - Optimal Ordering/Class Exercise.java: -------------------------------------------------------------------------------- 1 | /* 2 | Problem Statement 3 | 4 | Sophia is managing a data analysis pipeline consisting of multiple computational units represented by matrices. Each unit takes the output from the previous unit as input. Sophia needs to optimize the computational flow by determining the minimum number of scalar multiplications required to process the sequence of matrices. 5 | 6 | Additionally, Sophia needs to find the optimal order of matrix multiplications to minimize processing time. 7 | 8 | Write a program to help Sophia calculate the minimum cost of matrix multiplications and display the optimal order. 9 | 10 | Input format: 11 | The first line contains a single integer n, representing the number of dimensions in the sequence. 12 | The second line contains n integers, representing the dimensions of the matrices. 13 | 14 | Output format: 15 | The first line contains an integer representing the minimum number of scalar multiplications required. 16 | The second line contains a string representing the optimal order of matrix multiplications. 17 | 18 | Refer to the sample output for formatting specifications. 19 | 20 | Code constraints: 21 | The given test cases fall under the following specifications: 22 | 3 ≤ n ≤ 100 23 | 1 ≤ dimensions of matrices ≤ 500 24 | 25 | Sample test cases: 26 | Input 1: 27 | 5 28 | 1 2 3 4 5 29 | 30 | Output 1: 31 | 38 32 | (((M1M2)M3)M4) 33 | 34 | Input 2: 35 | 3 36 | 1 2 3 37 | 38 | Output 2: 39 | 6 40 | (M1M2) 41 | */ 42 | 43 | 44 | 45 | import java.util.*; 46 | 47 | class MatrixChainMultiplication { 48 | 49 | // Recursive function to compute minimum cost of matrix chain multiplication 50 | public static int minMultRec(int[] arr, int i, int j, int[][] memo, int[][] brackets) { 51 | if (i + 1 == j) { 52 | return 0; 53 | } 54 | if (memo[i][j] != -1) { 55 | return memo[i][j]; 56 | } 57 | 58 | int res = Integer.MAX_VALUE; 59 | for (int k = i + 1; k < j; k++) { 60 | int curr = minMultRec(arr, i, k, memo, brackets) + 61 | minMultRec(arr, k, j, memo, brackets) + 62 | arr[i] * arr[k] * arr[j]; 63 | 64 | if (curr < res) { 65 | res = curr; 66 | brackets[i][j] = k; 67 | } 68 | } 69 | 70 | memo[i][j] = res; 71 | return res; 72 | } 73 | 74 | // Function to build the order of matrix multiplications 75 | public static void getOrder(int i, int j, int[][] brackets, StringBuilder order) { 76 | if (i + 1 == j) { 77 | order.append("M").append(i + 1); 78 | return; 79 | } 80 | 81 | order.append("("); 82 | getOrder(i, brackets[i][j], brackets, order); 83 | getOrder(brackets[i][j], j, brackets, order); 84 | order.append(")"); 85 | } 86 | 87 | // Main function for matrix chain multiplication 88 | public static int matrixMultiplication(int[] arr, int n, StringBuilder order) { 89 | int[][] memo = new int[n][n]; 90 | int[][] brackets = new int[n][n]; 91 | 92 | // Initialize memo and brackets arrays 93 | for (int i = 0; i < n; i++) { 94 | Arrays.fill(memo[i], -1); 95 | Arrays.fill(brackets[i], -1); 96 | } 97 | 98 | int minCost = minMultRec(arr, 0, n - 1, memo, brackets); 99 | getOrder(0, n - 1, brackets, order); 100 | 101 | return minCost; 102 | } 103 | 104 | public static void main(String[] args) { 105 | Scanner sc = new Scanner(System.in); 106 | 107 | // Input size of matrix chain 108 | int n = sc.nextInt(); 109 | 110 | // Input dimensions of matrices 111 | int[] arr = new int[n]; 112 | for (int i = 0; i < n; i++) { 113 | arr[i] = sc.nextInt(); 114 | } 115 | 116 | // StringBuilder to store the optimal multiplication order 117 | StringBuilder optimalOrder = new StringBuilder(); 118 | 119 | // Calculate minimum cost and the order of multiplication 120 | int result = matrixMultiplication(arr, n, optimalOrder); 121 | 122 | // Output the result 123 | System.out.println(result); 124 | System.out.println(optimalOrder.toString()); 125 | 126 | sc.close(); 127 | } 128 | } 129 | 130 | 131 | 132 | /* 133 | Problem Statement 134 | 135 | Emily is managing a factory that operates on sequential machines represented by matrices. Each machine outputs data in a format that matches the input dimensions of the next machine. To reduce processing time, Emily wants to determine the minimum number of scalar operations required to process the sequence. 136 | 137 | Additional Constraint: It should display the optimal order of the Multiplication. 138 | 139 | Help Emily to complete the task. 140 | 141 | Input format: 142 | The first line contains a single integer n, representing the number of dimensions in the array. 143 | The second line contains n integers, representing the dimensions of the matrices. 144 | 145 | Output format: 146 | The output prints the minimum scalar multiplications considering the given constraint. 147 | And then it displays the optimal order of the Multiplication. 148 | 149 | Refer to the sample output for formatting specifications. 150 | 151 | Code constraints: 152 | The given test cases fall under the following specifications: 153 | 3 ≤ n ≤ 100 154 | 1 ≤ dimensions of matrices ≤ 500 155 | 156 | Sample test cases: 157 | Input 1: 158 | 5 159 | 1 2 3 4 3 160 | 161 | Output 1: 162 | 30 163 | (((M1M2)M3)M4) 164 | 165 | Input 2: 166 | 3 167 | 10 20 30 168 | 169 | Output 2: 170 | 6000 171 | (M1M2) 172 | */ 173 | 174 | 175 | import java.util.*; 176 | 177 | class MatrixChainMultiplication { 178 | 179 | // Recursive function to compute minimum cost of matrix chain multiplication 180 | public static int minMultRec(int[] arr, int i, int j, int[][] memo, int[][] brackets) { 181 | if (i + 1 == j) { 182 | return 0; 183 | } 184 | if (memo[i][j] != -1) { 185 | return memo[i][j]; 186 | } 187 | 188 | int res = Integer.MAX_VALUE; 189 | for (int k = i + 1; k < j; k++) { 190 | int curr = minMultRec(arr, i, k, memo, brackets) + 191 | minMultRec(arr, k, j, memo, brackets) + 192 | arr[i] * arr[k] * arr[j]; 193 | 194 | if (curr < res) { 195 | res = curr; 196 | brackets[i][j] = k; 197 | } 198 | } 199 | 200 | memo[i][j] = res; 201 | return res; 202 | } 203 | 204 | // Function to build the order of matrix multiplications 205 | public static void getOrder(int i, int j, int[][] brackets, StringBuilder order) { 206 | if (i + 1 == j) { 207 | order.append("M").append(i + 1); 208 | return; 209 | } 210 | 211 | order.append("("); 212 | getOrder(i, brackets[i][j], brackets, order); 213 | getOrder(brackets[i][j], j, brackets, order); 214 | order.append(")"); 215 | } 216 | 217 | // Main function for matrix chain multiplication 218 | public static int matrixMultiplication(int[] arr, int n, StringBuilder order) { 219 | int[][] memo = new int[n][n]; 220 | int[][] brackets = new int[n][n]; 221 | 222 | // Initialize memo and brackets arrays 223 | for (int i = 0; i < n; i++) { 224 | Arrays.fill(memo[i], -1); 225 | Arrays.fill(brackets[i], -1); 226 | } 227 | 228 | int minCost = minMultRec(arr, 0, n - 1, memo, brackets); 229 | getOrder(0, n - 1, brackets, order); 230 | 231 | return minCost; 232 | } 233 | 234 | public static void main(String[] args) { 235 | Scanner sc = new Scanner(System.in); 236 | 237 | // Input size of matrix chain 238 | int n = sc.nextInt(); 239 | 240 | // Input dimensions of matrices 241 | int[] arr = new int[n]; 242 | for (int i = 0; i < n; i++) { 243 | arr[i] = sc.nextInt(); 244 | } 245 | 246 | // StringBuilder to store the optimal multiplication order 247 | StringBuilder optimalOrder = new StringBuilder(); 248 | 249 | // Calculate minimum cost and the order of multiplication 250 | int result = matrixMultiplication(arr, n, optimalOrder); 251 | 252 | // Output the result 253 | System.out.println(result); 254 | System.out.println(optimalOrder.toString()); 255 | 256 | sc.close(); 257 | } 258 | } 259 | 260 | 261 | -------------------------------------------------------------------------------- /Lab 4 - Optimal Ordering/Practice At Home.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * Alice is tasked with solving the Matrix Chain Multiplication problem using a dynamic programming approach. 5 | * Given a sequence of matrices and their dimensions, her goal is to determine the minimum number of scalar multiplications 6 | * required to compute the matrix product. 7 | * 8 | * The problem is to find the optimal order of matrix multiplication, as the order in which the matrices are multiplied 9 | * affects the number of operations. 10 | * 11 | * Alice needs help in completing this task. 12 | * 13 | * Input format: 14 | * The first line contains a single integer `n`, representing the number of dimensions in the array. 15 | * 16 | * The second line contains `n` integers, p[0], p[1], ..., p[n-1], where p[i] represents the dimensions of the matrices. 17 | * 18 | * Output format: 19 | * The output should print a single integer, the minimum number of scalar multiplications required to compute the product 20 | * of the matrices in the optimal order. 21 | * 22 | * Code constraints: 23 | * - 3 ≤ n ≤ 100 24 | * - 1 ≤ p[i] ≤ 500 25 | * 26 | * Sample test cases: 27 | * Input 1: 28 | * 5 29 | * 1 2 3 4 3 30 | * Output 1: 31 | * 30 32 | * 33 | * Input 2: 34 | * 3 35 | * 10 20 30 36 | * Output 2: 37 | * 6000 38 | */ 39 | 40 | 41 | import java.util.Scanner; 42 | 43 | class MatrixChainMultiplication { 44 | 45 | // Recursive function with memoization to compute the minimum multiplication cost 46 | public static int minMultRec(int[] arr, int i, int j, int[][] memo) { 47 | // Base case: No multiplication needed for a single matrix 48 | if (i + 1 == j) { 49 | return 0; 50 | } 51 | 52 | // Return the result from memo if already computed 53 | if (memo[i][j] != -1) { 54 | return memo[i][j]; 55 | } 56 | 57 | int res = Integer.MAX_VALUE; 58 | 59 | // Try all possible places to split the chain 60 | for (int k = i + 1; k < j; k++) { 61 | int curr = minMultRec(arr, i, k, memo) + minMultRec(arr, k, j, memo) + arr[i] * arr[k] * arr[j]; 62 | 63 | if (curr < res) { 64 | res = curr; 65 | } 66 | } 67 | 68 | // Store the result in memo 69 | memo[i][j] = res; 70 | return res; 71 | } 72 | 73 | // Main function to calculate the matrix chain multiplication minimum cost 74 | public static int matrixMultiplication(int[] arr, int n) { 75 | int[][] memo = new int[n][n]; 76 | 77 | // Initialize the memoization table with -1 (indicating not computed) 78 | for (int i = 0; i < n; i++) { 79 | for (int j = 0; j < n; j++) { 80 | memo[i][j] = -1; 81 | } 82 | } 83 | 84 | // Call the recursive function to get the result 85 | return minMultRec(arr, 0, n - 1, memo); 86 | } 87 | 88 | public static void main(String[] args) { 89 | Scanner sc = new Scanner(System.in); 90 | 91 | // Input the number of matrices (n) 92 | int n = sc.nextInt(); 93 | 94 | // Input the dimensions of matrices 95 | int[] arr = new int[n]; 96 | for (int i = 0; i < n; i++) { 97 | arr[i] = sc.nextInt(); 98 | } 99 | 100 | // Call the function to get the result 101 | int result = matrixMultiplication(arr, n); 102 | 103 | // Output the result 104 | System.out.println(result); 105 | 106 | sc.close(); 107 | } 108 | } 109 | 110 | 111 | /* 112 | * Problem Statement: 113 | * 114 | * Liam is simulating complex weather patterns using matrices. His simulation requires accurate and efficient calculations 115 | * for matrix multiplications. To optimize the computation process, the middle matrix (if any) should always be used as 116 | * the base for splitting the computation, followed by recursive evaluations. 117 | * 118 | * When calculating the optimal order of matrix multiplications, always prioritize splitting using the middle matrix first 119 | * if n ≥ 3. 120 | * 121 | * Input format: 122 | * The first line contains a single integer n, representing the number of dimensions in the array. 123 | * 124 | * The second line contains n integers, representing the dimensions of the matrices. 125 | * 126 | * Output format: 127 | * The output prints: 128 | * 1. The minimum number of scalar multiplications required to compute the matrix product. 129 | * 2. The optimal sequence of matrix splits that minimizes scalar multiplications, starting with the middle matrix split. 130 | * 131 | * Code constraints: 132 | * - 3 ≤ n ≤ 100 133 | * - 1 ≤ dimensions of matrices ≤ 500 134 | * 135 | * Sample test cases: 136 | * Input 1: 137 | * 5 138 | * 1 2 3 4 3 139 | * Output 1: 140 | * 51 141 | * Optimal computation starts with a split at matrix 2 (dimensions: 3 x 4). 142 | * 143 | * Input 2: 144 | * 3 145 | * 10 20 30 146 | * Output 2: 147 | * 6000 148 | * Optimal computation starts with a split at matrix 1 (dimensions: 20 x 30). 149 | */ 150 | 151 | 152 | 153 | import java.util.Scanner; 154 | 155 | class MatrixChainMultiplication { 156 | 157 | // Function to find the middle index of the chain 158 | public static int findMiddleIndex(int start, int end) { 159 | return (start + end) / 2; 160 | } 161 | 162 | // Recursive function to compute minimum multiplication cost using dynamic programming 163 | public static int minMultiplications(int[] arr, int i, int j, int[][] dp, boolean useMiddle) { 164 | if (i + 1 == j) { 165 | return 0; // Base case: No multiplication needed for a single matrix 166 | } 167 | 168 | if (dp[i][j] != -1) { 169 | return dp[i][j]; // Return already computed value 170 | } 171 | 172 | int minCost = Integer.MAX_VALUE; 173 | 174 | if (useMiddle) { 175 | // If we are using the middle index for the first split 176 | int mid = findMiddleIndex(i, j); 177 | int cost = minMultiplications(arr, i, mid, dp, false) + 178 | minMultiplications(arr, mid, j, dp, false) + 179 | arr[i] * arr[mid] * arr[j]; 180 | minCost = Math.min(minCost, cost); 181 | } else { 182 | // Try all possible splits for the minimum cost 183 | for (int k = i + 1; k < j; k++) { 184 | int cost = minMultiplications(arr, i, k, dp, false) + 185 | minMultiplications(arr, k, j, dp, false) + 186 | arr[i] * arr[k] * arr[j]; 187 | minCost = Math.min(minCost, cost); 188 | } 189 | } 190 | 191 | dp[i][j] = minCost; // Store the result in dp table 192 | return minCost; 193 | } 194 | 195 | // Main function to compute the minimum multiplication cost for the matrix chain 196 | public static int matrixChainMultiplication(int[] arr, int n) { 197 | int[][] dp = new int[n][n]; 198 | 199 | // Initialize the dp array with -1 200 | for (int i = 0; i < n; i++) { 201 | for (int j = 0; j < n; j++) { 202 | dp[i][j] = -1; 203 | } 204 | } 205 | 206 | // Call the recursive function starting with using middle index for the first split 207 | return minMultiplications(arr, 0, n - 1, dp, true); 208 | } 209 | 210 | public static void main(String[] args) { 211 | Scanner sc = new Scanner(System.in); 212 | 213 | // Input the number of matrices (n) 214 | int n = sc.nextInt(); 215 | 216 | // Input the dimensions of matrices 217 | int[] arr = new int[n]; 218 | for (int i = 0; i < n; i++) { 219 | arr[i] = sc.nextInt(); 220 | } 221 | 222 | // Compute the result using matrix chain multiplication 223 | int result = matrixChainMultiplication(arr, n); 224 | 225 | // Output the minimum number of multiplications required 226 | System.out.println(result); 227 | 228 | // Find the middle index for optimal computation split 229 | int mid = findMiddleIndex(0, n - 1); 230 | System.out.printf("Optimal computation starts with a split at matrix %d (dimensions: %d x %d).\n", 231 | mid, arr[mid], arr[mid + 1]); 232 | 233 | sc.close(); 234 | } 235 | } 236 | 237 | 238 | /* 239 | * Problem Statement: 240 | * 241 | * Ava is training a neural network where each layer is represented by a matrix. To save on energy and computation, 242 | * the multiplications should avoid splitting matrices with large dimensions at the start. 243 | * 244 | * Variation: Avoid splitting on the matrix with the largest dimension until all others are considered. 245 | * 246 | * Input format: 247 | * - The first line contains a single integer n, representing the number of dimensions in the array. 248 | * - The second line contains n integers, p[0], p[1], ..., p[n-1], where p[i] represents the dimensions of the matrices. 249 | * 250 | * Output format: 251 | * - The output prints a single integer, the minimum number of scalar multiplications required to compute the product 252 | * of the matrices in the optimal order. 253 | * 254 | * Code constraints: 255 | * - 3 ≤ n ≤ 100 256 | * - 1 ≤ p[i] ≤ 500 257 | * 258 | * Sample test cases: 259 | * Input 1: 260 | * 5 261 | * 1 2 3 4 3 262 | * Output 1: 263 | * 51 264 | * 265 | * Input 2: 266 | * 3 267 | * 10 20 30 268 | * Output 2: 269 | * 6000 270 | */ 271 | 272 | 273 | 274 | import java.util.Scanner; 275 | 276 | class MatrixChainMultiplication { 277 | 278 | // Function to find the matrix with the largest dimension in the range (start, end) 279 | public static int findLargestDimension(int[] arr, int start, int end) { 280 | int maxIndex = start; 281 | for (int i = start + 1; i < end; i++) { 282 | if (arr[i] > arr[maxIndex]) { 283 | maxIndex = i; 284 | } 285 | } 286 | return maxIndex; 287 | } 288 | 289 | // Function to compute the minimum cost of matrix chain multiplication 290 | public static int matrixChainMultiplication(int[] arr, int n) { 291 | int[][] dp = new int[n][n]; 292 | 293 | // Initialize the dp array with 0 294 | for (int i = 0; i < n; i++) { 295 | for (int j = 0; j < n; j++) { 296 | dp[i][j] = 0; 297 | } 298 | } 299 | 300 | // Compute the minimum multiplication cost for chains of increasing lengths 301 | for (int length = 2; length < n; length++) { 302 | for (int i = 0; i < n - length; i++) { 303 | int j = i + length; 304 | dp[i][j] = Integer.MAX_VALUE; 305 | 306 | // Find the largest dimension in the current chain 307 | int largestDimIndex = findLargestDimension(arr, i + 1, j); 308 | 309 | // Try splitting the chain at all possible positions 310 | for (int k = i + 1; k < j; k++) { 311 | // Skip the largest dimension if the chain length is greater than 2 312 | if (k == largestDimIndex && j - i > 2) { 313 | continue; 314 | } 315 | 316 | int cost = dp[i][k] + dp[k][j] + arr[i] * arr[k] * arr[j]; 317 | if (cost < dp[i][j]) { 318 | dp[i][j] = cost; 319 | } 320 | } 321 | } 322 | } 323 | 324 | // Return the minimum cost to multiply all matrices 325 | return dp[0][n - 1]; 326 | } 327 | 328 | public static void main(String[] args) { 329 | Scanner sc = new Scanner(System.in); 330 | 331 | // Input the number of matrices (n) 332 | int n = sc.nextInt(); 333 | 334 | // Input the dimensions of matrices 335 | int[] arr = new int[n]; 336 | for (int i = 0; i < n; i++) { 337 | arr[i] = sc.nextInt(); 338 | } 339 | 340 | // Call the function to calculate the result 341 | int result = matrixChainMultiplication(arr, n); 342 | 343 | // Output the result 344 | System.out.print(result); 345 | 346 | sc.close(); 347 | } 348 | } 349 | 350 | 351 | -------------------------------------------------------------------------------- /Lab 5 - Shortest Path Algorithm/Challenge Yourself.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * Raghav is working on mastering graph algorithms, and his mentor has presented a challenge involving a directed graph 4 | * characterized by 4 vertices and 4 edges. Each edge in the graph has a specific weight representing the distance between 5 | * two vertices. Raghav must implement the Floyd-Warshall algorithm and reconstruct the shortest paths linking the vertices. 6 | * 7 | * Input format: 8 | * The input consists of four lines, each containing four space-separated integers representing the adjacency matrix of the graph. 9 | * Each integer represents the weight of the edge between two vertices. 10 | * Use 999 to represent infinity if there is no direct edge between two vertices. 11 | * 12 | * Output format: 13 | * The output consists of two main parts: 14 | * 1. The 4x4 matrix representing the shortest distance between all pairs of vertices. 15 | * 2. The shortest paths between every pair of vertices, where each shortest path is printed in the format "Shortest path from node u to node v: ". 16 | * 17 | * Code constraints: 18 | * - 0 ≤ Weight of edge ≤ 999 19 | * 20 | * Sample Test Case: 21 | * Input 1: 22 | * 0 3 999 7 23 | * 8 0 2 999 24 | * 5 999 0 1 25 | * 2 999 999 0 26 | * Output 1: 27 | * 0 3 5 6 28 | * 5 0 2 3 29 | * 3 6 0 1 30 | * 2 5 7 0 31 | * Shortest paths between every pair of vertices: 32 | * Shortest path from node 0 to node 1: 0 -> 1 33 | * Shortest path from node 0 to node 2: 0 -> 1 -> 2 34 | * Shortest path from node 0 to node 3: 0 -> 1 -> 2 -> 3 35 | * Shortest path from node 1 to node 0: 1 -> 2 -> 3 -> 0 36 | * Shortest path from node 1 to node 2: 1 -> 2 37 | * Shortest path from node 1 to node 3: 1 -> 2 -> 3 38 | * Shortest path from node 2 to node 0: 2 -> 3 -> 0 39 | * Shortest path from node 2 to node 1: 2 -> 3 -> 0 -> 1 40 | * Shortest path from node 2 to node 3: 2 -> 3 41 | * Shortest path from node 3 to node 0: 3 -> 0 42 | * Shortest path from node 3 to node 1: 3 -> 0 -> 1 43 | * Shortest path from node 3 to node 2: 3 -> 0 -> 1 -> 2 44 | * 45 | * Input 2: 46 | * 0 3 999 4 47 | * 9 5 0 2 48 | * 5 999 0 1 49 | * 2 999 999 0 50 | * Output 2: 51 | * 0 3 3 4 52 | * 3 5 0 1 53 | * 3 6 0 1 54 | * 2 5 5 0 55 | * Shortest paths between every pair of vertices: 56 | * Shortest path from node 0 to node 1: 0 -> 1 57 | * Shortest path from node 0 to node 2: 0 -> 1 -> 2 58 | * Shortest path from node 0 to node 3: 0 -> 3 59 | * Shortest path from node 1 to node 0: 1 -> 2 -> 3 -> 0 60 | * Shortest path from node 1 to node 2: 1 -> 2 61 | * Shortest path from node 1 to node 3: 1 -> 2 -> 3 62 | * Shortest path from node 2 to node 0: 2 -> 3 -> 0 63 | * Shortest path from node 2 to node 1: 2 -> 3 -> 0 -> 1 64 | * Shortest path from node 2 to node 3: 2 -> 3 65 | * Shortest path from node 3 to node 0: 3 -> 0 66 | * Shortest path from node 3 to node 1: 3 -> 0 -> 1 67 | * Shortest path from node 3 to node 2: 3 -> 0 -> 1 -> 2 68 | */ 69 | 70 | 71 | import java.util.Scanner; 72 | 73 | class FloydWarshallAlgorithm { 74 | 75 | static final int V = 4; 76 | static final int INF = 99999; 77 | 78 | // Function to print the solution matrix and shortest paths 79 | static void printSolution(int[][] dist, int[][] next) { 80 | // Print the distance matrix 81 | for (int i = 0; i < V; i++) { 82 | for (int j = 0; j < V; j++) { 83 | if (dist[i][j] == INF) { 84 | System.out.print("INF "); 85 | } else { 86 | System.out.print(dist[i][j] + " "); 87 | } 88 | } 89 | System.out.println(); 90 | } 91 | 92 | // Print the shortest paths 93 | System.out.println("Shortest paths between every pair of vertices:"); 94 | for (int i = 0; i < V; i++) { 95 | for (int j = 0; j < V; j++) { 96 | if (i != j && next[i][j] != -1) { 97 | System.out.print("Shortest path from node " + i + " to node " + j + ": " + i); 98 | int nextNode = next[i][j]; 99 | while (nextNode != j) { 100 | System.out.print(" -> " + nextNode); 101 | nextNode = next[nextNode][j]; 102 | } 103 | System.out.println(" -> " + j); 104 | } 105 | } 106 | } 107 | } 108 | 109 | // Function to perform Floyd-Warshall algorithm 110 | static void floydWarshall(int[][] graph) { 111 | int[][] dist = new int[V][V]; 112 | int[][] next = new int[V][V]; 113 | 114 | // Initialize dist[][] and next[][] 115 | for (int i = 0; i < V; i++) { 116 | for (int j = 0; j < V; j++) { 117 | dist[i][j] = graph[i][j]; 118 | if (graph[i][j] != INF && i != j) { 119 | next[i][j] = j; 120 | } else { 121 | next[i][j] = -1; 122 | } 123 | } 124 | } 125 | 126 | // Apply Floyd-Warshall algorithm 127 | for (int k = 0; k < V; k++) { 128 | for (int i = 0; i < V; i++) { 129 | for (int j = 0; j < V; j++) { 130 | if (dist[i][k] + dist[k][j] < dist[i][j]) { 131 | dist[i][j] = dist[i][k] + dist[k][j]; 132 | next[i][j] = next[i][k]; 133 | } 134 | } 135 | } 136 | } 137 | 138 | printSolution(dist, next); 139 | } 140 | 141 | // Driver program 142 | public static void main(String[] args) { 143 | Scanner scanner = new Scanner(System.in); 144 | int[][] graph = new int[V][V]; 145 | 146 | // Read the adjacency matrix of the graph 147 | for (int i = 0; i < V; i++) { 148 | for (int j = 0; j < V; j++) { 149 | graph[i][j] = scanner.nextInt(); 150 | } 151 | } 152 | 153 | floydWarshall(graph); 154 | scanner.close(); 155 | } 156 | } 157 | 158 | 159 | 160 | /* 161 | * Problem Statement: 162 | * 163 | * Venu, being passionate about algorithms, decides to implement the Floyd-Warshall algorithm to find the transitive closure of a directed graph. 164 | * 165 | * The graph is represented by its adjacency matrix, where the value 999 represents the absence of a direct edge between two vertices. 166 | * Venu wants to write a program to find the transitive closure of this graph and print the resulting matrix. 167 | * 168 | * Input format: 169 | * The first line contains two space-separated integers n and e, denoting the number of vertices and the number of edges in the graph. 170 | * 171 | * Each of the next e lines contains three space-separated integers u, v, and w, where: 172 | * - u and v represent the vertices of the directed edge. 173 | * - w represents the weight of the edge. 174 | * 175 | * Output format: 176 | * The output displays the integers, representing the transitive closure of the given graph in the form of an n x n matrix. 177 | * 178 | * Note: 179 | * - Rows and columns should be separated by tab space. 180 | * 181 | * Code constraints: 182 | * - 1 ≤ n ≤ 10 (number of vertices) 183 | * - 1 ≤ e ≤ 10 (number of edges) 184 | * - 1 ≤ u, v ≤ n (vertex numbers) 185 | * - 1 ≤ w ≤ 999 (weight of edge) 186 | * 187 | * Sample Test Cases: 188 | * 189 | * Input 1: 190 | * 3 3 191 | * 1 2 3 192 | * 2 3 1 193 | * 3 1 4 194 | * 195 | * Output 1: 196 | * Transitive closure 197 | * 0 3 4 198 | * 5 0 1 199 | * 4 7 0 200 | * 201 | * Input 2: 202 | * 3 3 203 | * 1 2 5 204 | * 2 3 7 205 | * 3 1 4 206 | * 207 | * Output 2: 208 | * Transitive closure 209 | * 0 5 12 210 | * 11 0 7 211 | * 4 9 0 212 | */ 213 | 214 | 215 | import java.util.Scanner; 216 | 217 | class FloydsAlgorithm { 218 | 219 | static int min(int a, int b) { 220 | return (a < b) ? a : b; 221 | } 222 | 223 | static void floyds(int[][] p, int n) { 224 | for (int k = 1; k <= n; k++) { 225 | for (int i = 1; i <= n; i++) { 226 | for (int j = 1; j <= n; j++) { 227 | if (i == j) { 228 | p[i][j] = 0; 229 | } else { 230 | p[i][j] = min(p[i][j], p[i][k] + p[k][j]); 231 | } 232 | } 233 | } 234 | } 235 | } 236 | 237 | public static void main(String[] args) { 238 | Scanner scanner = new Scanner(System.in); 239 | 240 | int[][] p = new int[11][11]; // Size 11 to handle 1-based indexing easily 241 | int w, n, e, u, v; 242 | 243 | n = scanner.nextInt(); 244 | e = scanner.nextInt(); 245 | 246 | for (int i = 1; i <= n; i++) { 247 | for (int j = 1; j <= n; j++) { 248 | p[i][j] = 999; 249 | } 250 | } 251 | 252 | for (int i = 1; i <= e; i++) { 253 | u = scanner.nextInt(); 254 | v = scanner.nextInt(); 255 | w = scanner.nextInt(); 256 | p[u][v] = w; 257 | } 258 | 259 | floyds(p, n); 260 | 261 | System.out.println("Transitive closure"); 262 | for (int i = 1; i <= n; i++) { 263 | for (int j = 1; j <= n; j++) { 264 | System.out.print(p[i][j] + "\t"); 265 | } 266 | System.out.println(); 267 | } 268 | 269 | scanner.close(); 270 | } 271 | } 272 | 273 | 274 | /* 275 | * Problem Statement: 276 | * 277 | * In a city, there are several locations connected by roads. Each road has a certain distance. 278 | * You are tasked with finding the shortest distances between all pairs of locations in the city 279 | * using the Floyd-Warshall algorithm. 280 | * 281 | * Write a program that calculates the shortest path between all pairs of locations in the city. 282 | * 283 | * Example Input: 284 | * 285 | * 4 286 | * 4 287 | * 0 1 3 288 | * 1 2 1 289 | * 2 3 1 290 | * 0 2 5 291 | * 292 | * Output: 293 | * 294 | * 0 3 4 5 295 | * 3 0 1 2 296 | * 4 1 0 1 297 | * 5 2 1 0 298 | * 299 | * Explanation: 300 | * 301 | * The city has 4 locations (0 to 3). 302 | * There are 4 roads connecting the locations. 303 | * The roads and their distances are: 304 | * 305 | * 0 → 1 with distance 3 306 | * 1 → 2 with distance 1 307 | * 2 → 3 with distance 1 308 | * 0 → 2 with distance 5 309 | * 310 | * Initially, the distance matrix is set to infinity (INF) except for direct roads and diagonal values (0). 311 | * The Floyd-Warshall algorithm updates the matrix by checking intermediate paths. 312 | * The shortest path from 0 to 2 (via 1) is updated to 4 (0 → 1 → 2) instead of 5. 313 | * The shortest path from 0 to 3 is 5 (0 → 1 → 2 → 3). 314 | * 315 | * The final distance matrix is printed, showing the shortest distances. 316 | * 317 | * 0 3 4 5 318 | * 3 0 1 2 319 | * 4 1 0 1 320 | * 5 2 1 0 321 | * 322 | * Input format: 323 | * 324 | * The first line contains an integer N, representing the number of locations in the city. 325 | * The second line contains an integer M, representing the number of roads in the city. 326 | * The next M lines each contain three space-separated integers: u, v, w where: 327 | * 328 | * u and v represent two locations connected by a road. 329 | * w represents the distance between u and v. 330 | * 331 | * Output format: 332 | * 333 | * The output prints a matrix, where the value at the i-th row and j-th column represents the shortest distance 334 | * between location i and location j. 335 | * 336 | * Code constraints: 337 | * 338 | * In this scenario, the given test cases will fall under the following constraints: 339 | * 2 ≤ N ≤ 5 340 | * 1 ≤ M ≤ 10 341 | * 0 ≤ w ≤ 100 342 | * 343 | * Sample Test Cases: 344 | * 345 | * Input 1: 346 | * 4 347 | * 4 348 | * 0 1 3 349 | * 1 2 1 350 | * 2 3 1 351 | * 0 2 5 352 | * 353 | * Output 1: 354 | * 0 3 4 5 355 | * 3 0 1 2 356 | * 4 1 0 1 357 | * 5 2 1 0 358 | * 359 | * Input 2: 360 | * 3 361 | * 3 362 | * 0 1 2 363 | * 1 2 3 364 | * 0 2 6 365 | * 366 | * Output 2: 367 | * 0 2 5 368 | * 2 0 3 369 | * 5 3 0 370 | */ 371 | 372 | 373 | 374 | import java.util.Scanner; 375 | 376 | interface GraphOperations { 377 | void floydWarshall(); 378 | void printSolution(); 379 | } 380 | 381 | class FloydWarshall implements GraphOperations { 382 | private int[][] dist; 383 | private int N; 384 | private static final int INF = Integer.MAX_VALUE; 385 | 386 | public FloydWarshall(int N, int M, Scanner sc) { 387 | this.N = N; 388 | dist = new int[N][N]; 389 | for (int i = 0; i < N; i++) { 390 | for (int j = 0; j < N; j++) { 391 | if (i == j) dist[i][j] = 0; 392 | else dist[i][j] = INF; 393 | } 394 | } 395 | for (int i = 0; i < M; i++) { 396 | int u = sc.nextInt(); 397 | int v = sc.nextInt(); 398 | int w = sc.nextInt(); 399 | dist[u][v] = dist[v][u] = Math.min(dist[u][v], w); 400 | } 401 | } 402 | 403 | @Override 404 | public void floydWarshall() { 405 | for (int k = 0; k < N; k++) { 406 | for (int i = 0; i < N; i++) { 407 | for (int j = 0; j < N; j++) { 408 | if (dist[i][k] != INF && dist[k][j] != INF && dist[i][j] > dist[i][k] + dist[k][j]) { 409 | dist[i][j] = dist[i][k] + dist[k][j]; 410 | } 411 | } 412 | } 413 | } 414 | } 415 | 416 | @Override 417 | public void printSolution() { 418 | for (int i = 0; i < N; i++) { 419 | for (int j = 0; j < N; j++) { 420 | System.out.print((dist[i][j] == INF ? "INF" : dist[i][j]) + " "); 421 | } 422 | System.out.println(); 423 | } 424 | } 425 | } 426 | 427 | public class Main { 428 | public static void main(String[] args) { 429 | Scanner sc = new Scanner(System.in); 430 | int N = sc.nextInt(); 431 | int M = sc.nextInt(); 432 | FloydWarshall graph = new FloydWarshall(N, M, sc); 433 | graph.floydWarshall(); 434 | graph.printSolution(); 435 | } 436 | } 437 | 438 | 439 | -------------------------------------------------------------------------------- /Lab 5 - Shortest Path Algorithm/Class Exercise.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * A traveler needs to find the shortest path between every pair of cities in a road network. 5 | * The cities are connected by roads, each with a specific travel cost. 6 | * To do this, the traveler uses the Floyd-Warshall Algorithm to calculate the shortest distances between every pair of cities in a given edge-weighted undirected graph. 7 | * 8 | * Example1: 9 | * 10 | * Input: 11 | * 4 12 | * 3 13 | * 0 1 2 14 | * 1 2 3 15 | * 2 3 4 16 | * 17 | * Output: 18 | * Original matrix 19 | * 0 2 INF INF 20 | * 2 0 3 INF 21 | * INF 3 0 4 22 | * INF INF 4 0 23 | * 24 | * Shortest path matrix 25 | * 0 2 5 9 26 | * 2 0 3 7 27 | * 5 3 0 4 28 | * 9 7 4 0 29 | * 30 | * Explanation: 31 | * Given: 4 nodes (0, 1, 2, 3) and 3 edges: 0 → 1 (weight 2), 1 → 2 (weight 3), 2 → 3 (weight 4) 32 | * 33 | * Any node pair without a direct edge is considered INF (unreachable initially). 34 | * Step 1: Construct Initial Graph (Original Matrix) 35 | * 0 2 INF INF 36 | * 2 0 3 INF 37 | * INF 3 0 4 38 | * INF INF 4 0 39 | * 40 | * Diagonal elements (self to self) are 0. 41 | * If no direct path exists, it's INF. 42 | * 43 | * Step 2: Running Floyd-Warshall Algorithm 44 | * Using node 0 as an intermediate: No updates since it only connects to node 1. 45 | * Using node 1 as an intermediate: 0 → 2 via 1: 0 → 1 (2) + 1 → 2 (3) = 5 46 | * 2 → 0 also updates to 5. 47 | * Using node 2 as an intermediate: 0 → 3 via 2: 0 → 2 (5) + 2 → 3 (4) = 9 48 | * 1 → 3 via 2: 1 → 2 (3) + 2 → 3 (4) = 7 49 | * Using node 3 as an intermediate: No further updates. 50 | * 51 | * Step 3: Final Shortest Path Matrix 52 | * 0 2 5 9 53 | * 2 0 3 7 54 | * 5 3 0 4 55 | * 9 7 4 0 56 | * 57 | * Input format: 58 | * The first line contains an integer V representing the number of cities (vertices) in the network. 59 | * The second line contains an integer E representing the number of roads (edges) in the network. 60 | * The next E lines each contain three space-separated integers u, v, w, where u and v represent the cities connected by a road, and w represents the travel cost (weight) of the road. 61 | * 62 | * Output format: 63 | * The first line of output prints the original matrix, where each entry represents the direct travel cost between two cities. If there is no direct road between two cities, represent the cost as INF. 64 | * Then, print the shortest path matrix, where each entry represents the shortest travel cost between every pair of cities, computed using the Floyd-Warshall algorithm. 65 | * 66 | * Code constraints: 67 | * The given test cases fall under the following specifications: 68 | * - 1 ≤ V ≤ 1000 69 | * - 0 ≤ E ≤ 10,000 70 | * - 0 ≤ u, v < V 71 | * - -1000 ≤ w ≤ 1000 72 | * 73 | * Sample test cases: 74 | * Input 1: 75 | * 4 76 | * 3 77 | * 0 1 2 78 | * 1 2 3 79 | * 2 3 4 80 | * Output 1: 81 | * Original matrix 82 | * 0 2 INF INF 83 | * 2 0 3 INF 84 | * INF 3 0 4 85 | * INF INF 4 0 86 | * 87 | * Shortest path matrix 88 | * 0 2 5 9 89 | * 2 0 3 7 90 | * 5 3 0 4 91 | * 9 7 4 0 92 | * 93 | * Input 2: 94 | * 5 95 | * 5 96 | * 0 1 2 97 | * 0 2 7 98 | * 1 2 3 99 | * 2 3 4 100 | * 3 4 5 101 | * Output 2: 102 | * Original matrix 103 | * 0 2 7 INF INF 104 | * 2 0 3 INF INF 105 | * 7 3 0 4 INF 106 | * INF INF 4 0 5 107 | * INF INF INF 5 0 108 | * 109 | * Shortest path matrix 110 | * 0 2 5 9 14 111 | * 2 0 3 7 12 112 | * 5 3 0 4 9 113 | * 9 7 4 0 5 114 | * 14 12 9 5 0 115 | */ 116 | 117 | 118 | 119 | // You are using Java 120 | import java.util.Scanner; 121 | 122 | public class Main { 123 | private static final int INF = Integer.MAX_VALUE; 124 | 125 | public static void main(String[] args) { 126 | Scanner scanner = new Scanner(System.in); 127 | 128 | // Read input 129 | int V = scanner.nextInt(); // Number of vertices 130 | int E = scanner.nextInt(); // Number of edges 131 | 132 | // Initialize distance matrix with INF 133 | int[][] graph = new int[V][V]; 134 | for (int i = 0; i < V; i++) { 135 | for (int j = 0; j < V; j++) { 136 | if (i == j) { 137 | graph[i][j] = 0; // Distance from a vertex to itself is 0 138 | } else { 139 | graph[i][j] = INF; // Initialize all other distances as infinite 140 | } 141 | } 142 | } 143 | 144 | // Add edges to the graph 145 | for (int i = 0; i < E; i++) { 146 | int u = scanner.nextInt(); 147 | int v = scanner.nextInt(); 148 | int w = scanner.nextInt(); 149 | 150 | // Since the graph is undirected 151 | graph[u][v] = w; 152 | graph[v][u] = w; 153 | } 154 | 155 | scanner.close(); 156 | 157 | // Print original matrix 158 | System.out.println("Original matrix"); 159 | printMatrix(graph, V); 160 | 161 | // Apply Floyd-Warshall algorithm 162 | int[][] shortestPaths = floydWarshall(graph, V); 163 | 164 | // Print shortest path matrix 165 | System.out.println("\nShortest path matrix"); 166 | printMatrix(shortestPaths, V); 167 | } 168 | 169 | // Implementation of Floyd-Warshall algorithm 170 | private static int[][] floydWarshall(int[][] graph, int V) { 171 | int[][] dist = new int[V][V]; 172 | 173 | // Initialize the distance matrix with the same values as the input graph 174 | for (int i = 0; i < V; i++) { 175 | for (int j = 0; j < V; j++) { 176 | dist[i][j] = graph[i][j]; 177 | } 178 | } 179 | 180 | // Consider each vertex as an intermediate vertex 181 | for (int k = 0; k < V; k++) { 182 | // Consider all pairs of vertices (i, j) 183 | for (int i = 0; i < V; i++) { 184 | for (int j = 0; j < V; j++) { 185 | // If vertex k is on the shortest path from i to j, 186 | // then update the value of dist[i][j] 187 | if (dist[i][k] != INF && dist[k][j] != INF && 188 | dist[i][k] + dist[k][j] < dist[i][j]) { 189 | dist[i][j] = dist[i][k] + dist[k][j]; 190 | } 191 | } 192 | } 193 | } 194 | 195 | return dist; 196 | } 197 | 198 | // Helper method to print the matrix 199 | private static void printMatrix(int[][] matrix, int V) { 200 | for (int i = 0; i < V; i++) { 201 | for (int j = 0; j < V; j++) { 202 | if (matrix[i][j] == INF) { 203 | System.out.print("INF "); 204 | } else { 205 | System.out.print(matrix[i][j] + " "); 206 | } 207 | } 208 | System.out.println(); 209 | } 210 | } 211 | } 212 | 213 | 214 | 215 | 216 | /* 217 | * Problem Statement: 218 | * 219 | * The Floyd-Warshall Algorithm is for solving all pairs of shortest-path problems. 220 | * The problem is to find the shortest distances between every pair of vertices in a given edge-weighted directed graph. 221 | * 222 | * Input format: 223 | * The first line of input represents the size N. 224 | * The next N*N Matrix represents the distance. 225 | * Note: The distance between one city and itself will be 0, and the distance will be 999 if there is no direct edge between the two cities. 226 | * 227 | * Output format: 228 | * The output prints the shortest distance between every pair of cities. 229 | * If there is no shortest path between two cities, then print INF. 230 | * 231 | * Sample test cases: 232 | * Input 1: 233 | * 4 234 | * 0 5 999 10 235 | * 999 0 3 999 236 | * 999 999 0 1 237 | * 999 999 999 0 238 | * Output 1: 239 | * 0 5 8 9 240 | * INF 0 3 4 241 | * INF INF 0 1 242 | * INF INF INF 0 243 | * 244 | * Explanation: 245 | * Given a graph with 4 cities, where: 246 | * - 0 → 1 with weight 5 247 | * - 1 → 2 with weight 3 248 | * - 2 → 3 with weight 1 249 | * For the first matrix: 250 | * - If there is no direct edge between two cities, the distance is represented as 999 (INF). 251 | * The algorithm will then compute the shortest path between every pair of cities using the Floyd-Warshall algorithm. 252 | * 253 | * Output: 254 | * The shortest paths matrix: 255 | * - City 0 to City 1 has a direct distance of 5. 256 | * - City 0 to City 2 can be reached through City 1 with a distance of 8 (5 + 3). 257 | * - City 0 to City 3 can be reached through City 2 with a distance of 9 (5 + 3 + 1). 258 | * 259 | * Similarly, the shortest paths for all pairs will be computed. 260 | */ 261 | 262 | 263 | 264 | 265 | import java.util.Scanner; 266 | 267 | public class Main { 268 | private static final int INF = 999; 269 | 270 | public static void main(String[] args) { 271 | Scanner scanner = new Scanner(System.in); 272 | 273 | // Read input size 274 | int N = scanner.nextInt(); 275 | 276 | // Initialize distance matrix 277 | int[][] dist = new int[N][N]; 278 | 279 | // Read the distance matrix 280 | for (int i = 0; i < N; i++) { 281 | for (int j = 0; j < N; j++) { 282 | dist[i][j] = scanner.nextInt(); 283 | } 284 | } 285 | 286 | scanner.close(); 287 | 288 | // Apply Floyd-Warshall algorithm 289 | floydWarshall(dist, N); 290 | 291 | // Print the result 292 | printMatrix(dist, N); 293 | } 294 | 295 | // Implementation of Floyd-Warshall algorithm 296 | private static void floydWarshall(int[][] dist, int N) { 297 | // Consider each vertex as an intermediate vertex 298 | for (int k = 0; k < N; k++) { 299 | // Consider all pairs of vertices (i, j) 300 | for (int i = 0; i < N; i++) { 301 | for (int j = 0; j < N; j++) { 302 | // If vertex k is on the shortest path from i to j, 303 | // then update the value of dist[i][j] 304 | if (dist[i][k] != INF && dist[k][j] != INF && 305 | dist[i][k] + dist[k][j] < dist[i][j]) { 306 | dist[i][j] = dist[i][k] + dist[k][j]; 307 | } 308 | } 309 | } 310 | } 311 | } 312 | 313 | // Helper method to print the matrix 314 | private static void printMatrix(int[][] matrix, int N) { 315 | for (int i = 0; i < N; i++) { 316 | for (int j = 0; j < N; j++) { 317 | if (matrix[i][j] == INF) { 318 | System.out.print("INF"); 319 | } else { 320 | System.out.print(matrix[i][j]); 321 | } 322 | 323 | // Add space after each element except the last one in a row 324 | if (j < N - 1) { 325 | System.out.print(" "); 326 | } 327 | } 328 | // Add newline after each row 329 | System.out.println(); 330 | } 331 | } 332 | } 333 | 334 | 335 | -------------------------------------------------------------------------------- /Lab 5 - Shortest Path Algorithm/Practice At Home.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * Sarah has been tasked with developing a program to determine the shortest paths among nodes 5 | * in a directed network represented as a graph containing nodes and weighted edges. 6 | * 7 | * Her goal is to implement the Floyd-Warshall algorithm to compute the shortest path matrix 8 | * for this directed network. 9 | * 10 | * Input format: 11 | * 12 | * The first line of input consists of an integer n, representing the number of nodes in the network. 13 | * 14 | * The next n lines contain space-separated integers, representing the adjacency matrix 'graph' of the network. 15 | * Each integer is the weight of the edge from node i to node j. 16 | * 17 | * Output format: 18 | * 19 | * The output prints the shortest path matrix as 'n x n' integers, where each element graph[i][j] represents 20 | * the shortest distance from node 'i' to node 'j'. 21 | * 22 | * Print each row of the matrix on a new line, with elements separated by a space. 23 | * 24 | * Code constraints: 25 | * 26 | * In this scenario, the given test cases will fall under the following constraints: 27 | * 28 | * 1 ≤ n ≤ 100 29 | * 0 ≤ weight of edge ≤ 999 30 | * graph[i][i] = 0 31 | * 32 | * Sample Test Cases: 33 | * 34 | * Input 1: 35 | * 4 36 | * 0 3 999 4 37 | * 8 0 2 999 38 | * 5 999 0 1 39 | * 2 999 999 0 40 | * 41 | * Output 1: 42 | * 0 3 5 4 43 | * 5 0 2 3 44 | * 3 6 0 1 45 | * 2 5 7 0 46 | * 47 | * Input 2: 48 | * 3 49 | * 0 1 2 50 | * 3 0 4 51 | * 5 6 0 52 | * 53 | * Output 2: 54 | * 0 1 2 55 | * 3 0 4 56 | * 5 6 0 57 | * 58 | * Input 3: 59 | * 4 60 | * 0 5 999 10 61 | * 999 0 3 999 62 | * 999 999 0 1 63 | * 999 999 999 0 64 | * 65 | * Output 3: 66 | * 0 5 8 9 67 | * 999 0 3 4 68 | * 999 999 0 1 69 | * 999 999 999 0 70 | */ 71 | 72 | 73 | 74 | import java.util.Scanner; 75 | 76 | class FloydWarshallAlgorithm { 77 | 78 | public static void floydWarshall(int[][] graph, int n) { 79 | int i, j, k; 80 | for (k = 0; k < n; k++) { 81 | for (i = 0; i < n; i++) { 82 | for (j = 0; j < n; j++) { 83 | if (graph[i][j] > graph[i][k] + graph[k][j]) { 84 | graph[i][j] = graph[i][k] + graph[k][j]; 85 | } 86 | } 87 | } 88 | } 89 | } 90 | 91 | public static void main(String[] args) { 92 | Scanner scanner = new Scanner(System.in); 93 | 94 | int n = scanner.nextInt(); 95 | int[][] graph = new int[n][n]; 96 | 97 | // Initialize the graph with maximum values and 0 on the diagonal 98 | for (int i = 0; i < n; i++) { 99 | for (int j = 0; j < n; j++) { 100 | if (i == j) { 101 | graph[i][j] = 0; 102 | } else { 103 | graph[i][j] = 100; 104 | } 105 | } 106 | } 107 | 108 | // Input the edges 109 | for (int i = 0; i < n; i++) { 110 | for (int j = 0; j < n; j++) { 111 | graph[i][j] = scanner.nextInt(); 112 | } 113 | } 114 | 115 | floydWarshall(graph, n); 116 | 117 | // Output the shortest paths 118 | for (int i = 0; i < n; i++) { 119 | for (int j = 0; j < n; j++) { 120 | System.out.print(graph[i][j] + " "); 121 | } 122 | System.out.println(); 123 | } 124 | 125 | scanner.close(); 126 | } 127 | } 128 | 129 | 130 | 131 | /* 132 | * Problem Statement: 133 | * 134 | * Rajesh is on a quest to master graph algorithms, and his mentor has presented him with an intriguing challenge. 135 | * He is given a directed graph consisting of four vertices and four edges, where each edge has a specific weight 136 | * representing the distance between two vertices. 137 | * 138 | * His task is twofold: 139 | * - First, he must implement the Floyd-Warshall algorithm to compute the shortest distances between all pairs of vertices. 140 | * - Second, he needs to reconstruct the shortest paths that connect these vertices. Assist Rajesh in accomplishing this challenge. 141 | * 142 | * Input format: 143 | * 144 | * The input consists of four lines, each containing four space-separated integers representing the adjacency matrix of the graph. 145 | * 146 | * Each integer represents the weight of the edge between two vertices. 147 | * Use 999 to represent infinity if there is no direct edge between two vertices. 148 | * 149 | * Output format: 150 | * 151 | * The output prints the 4x4 matrix representing the shortest distance. 152 | * 153 | * The next line prints "Shortest paths between every pair of vertices:". 154 | * 155 | * The next line prints the shortest paths between every pair of vertices. For each pair of vertices (u, v), in the format 156 | * of "Shortest paths from node u to node v: ", separated by arrows "->". 157 | * 158 | * Refer to the sample output for the formatting specifications. 159 | * 160 | * Code constraints: 161 | * 162 | * In this scenario, the given test cases will fall under the following constraints: 163 | * 164 | * 0 ≤ Weight of edge ≤ 999 165 | * 166 | * Sample Test Cases: 167 | * 168 | * Input 1: 169 | * 0 3 999 7 170 | * 8 0 2 999 171 | * 5 999 0 1 172 | * 2 999 999 0 173 | * 174 | * Output 1: 175 | * 0 3 5 6 176 | * 5 0 2 3 177 | * 3 6 0 1 178 | * 2 5 7 0 179 | * Shortest paths between every pair of vertices: 180 | * Shortest path from node 0 to node 1: 0 -> 1 181 | * Shortest path from node 0 to node 2: 0 -> 1 -> 2 182 | * Shortest path from node 0 to node 3: 0 -> 1 -> 2 -> 3 183 | * Shortest path from node 1 to node 0: 1 -> 2 -> 3 -> 0 184 | * Shortest path from node 1 to node 2: 1 -> 2 185 | * Shortest path from node 1 to node 3: 1 -> 2 -> 3 186 | * Shortest path from node 2 to node 0: 2 -> 3 -> 0 187 | * Shortest path from node 2 to node 1: 2 -> 3 -> 0 -> 1 188 | * Shortest path from node 2 to node 3: 2 -> 3 189 | * Shortest path from node 3 to node 0: 3 -> 0 190 | * Shortest path from node 3 to node 1: 3 -> 0 -> 1 191 | * Shortest path from node 3 to node 2: 3 -> 0 -> 1 -> 2 192 | * 193 | * Input 2: 194 | * 0 3 999 4 195 | * 9 5 0 2 196 | * 5 999 0 1 197 | * 2 999 999 0 198 | * 199 | * Output 2: 200 | * 0 3 3 4 201 | * 3 5 0 1 202 | * 3 6 0 1 203 | * 2 5 5 0 204 | * Shortest paths between every pair of vertices: 205 | * Shortest path from node 0 to node 1: 0 -> 1 206 | * Shortest path from node 0 to node 2: 0 -> 1 -> 2 207 | * Shortest path from node 0 to node 3: 0 -> 3 208 | * Shortest path from node 1 to node 0: 1 -> 2 -> 3 -> 0 209 | * Shortest path from node 1 to node 2: 1 -> 2 210 | * Shortest path from node 1 to node 3: 1 -> 2 -> 3 211 | * Shortest path from node 2 to node 0: 2 -> 3 -> 0 212 | * Shortest path from node 2 to node 1: 2 -> 3 -> 0 -> 1 213 | * Shortest path from node 2 to node 3: 2 -> 3 214 | * Shortest path from node 3 to node 0: 3 -> 0 215 | * Shortest path from node 3 to node 1: 3 -> 0 -> 1 216 | * Shortest path from node 3 to node 2: 3 -> 0 -> 1 -> 2 217 | */ 218 | 219 | 220 | 221 | import java.util.Scanner; 222 | 223 | class FloydWarshallAlgorithm { 224 | 225 | static final int V = 4; 226 | static final int INF = 99999; 227 | 228 | // Function to print the solution matrix and shortest paths 229 | static void printSolution(int[][] dist, int[][] next) { 230 | // Print the distance matrix 231 | for (int i = 0; i < V; i++) { 232 | for (int j = 0; j < V; j++) { 233 | if (dist[i][j] == INF) { 234 | System.out.print("INF "); 235 | } else { 236 | System.out.print(dist[i][j] + " "); 237 | } 238 | } 239 | System.out.println(); 240 | } 241 | 242 | // Print the shortest paths 243 | System.out.println("Shortest paths between every pair of vertices:"); 244 | for (int i = 0; i < V; i++) { 245 | for (int j = 0; j < V; j++) { 246 | if (i != j && next[i][j] != -1) { 247 | System.out.print("Shortest path from node " + i + " to node " + j + ": " + i); 248 | int nextNode = next[i][j]; 249 | while (nextNode != j) { 250 | System.out.print(" -> " + nextNode); 251 | nextNode = next[nextNode][j]; 252 | } 253 | System.out.println(" -> " + j); 254 | } 255 | } 256 | } 257 | } 258 | 259 | // Function to perform Floyd-Warshall algorithm 260 | static void floydWarshall(int[][] graph) { 261 | int[][] dist = new int[V][V]; 262 | int[][] next = new int[V][V]; 263 | 264 | // Initialize dist[][] and next[][] 265 | for (int i = 0; i < V; i++) { 266 | for (int j = 0; j < V; j++) { 267 | dist[i][j] = graph[i][j]; 268 | if (graph[i][j] != INF && i != j) { 269 | next[i][j] = j; 270 | } else { 271 | next[i][j] = -1; 272 | } 273 | } 274 | } 275 | 276 | // Apply Floyd-Warshall algorithm 277 | for (int k = 0; k < V; k++) { 278 | for (int i = 0; i < V; i++) { 279 | for (int j = 0; j < V; j++) { 280 | if (dist[i][k] + dist[k][j] < dist[i][j]) { 281 | dist[i][j] = dist[i][k] + dist[k][j]; 282 | next[i][j] = next[i][k]; 283 | } 284 | } 285 | } 286 | } 287 | 288 | printSolution(dist, next); 289 | } 290 | 291 | // Driver program 292 | public static void main(String[] args) { 293 | Scanner scanner = new Scanner(System.in); 294 | int[][] graph = new int[V][V]; 295 | 296 | // Read the adjacency matrix of the graph 297 | for (int i = 0; i < V; i++) { 298 | for (int j = 0; j < V; j++) { 299 | graph[i][j] = scanner.nextInt(); 300 | } 301 | } 302 | 303 | floydWarshall(graph); 304 | scanner.close(); 305 | } 306 | } 307 | 308 | 309 | /* 310 | * Problem Statement: 311 | * 312 | * Bhargavi is a dedicated network engineer working on optimizing communication routes within a computer network. 313 | * She is facing the challenge of finding the shortest paths between different nodes in a network. 314 | * Bhargavi knows about the Floyd-Warshall algorithm, which is an efficient way to solve this problem. 315 | * 316 | * Help her write a program that takes input data representing a network and calculates the shortest paths between 317 | * all pairs of nodes using the Floyd-Warshall algorithm. 318 | * 319 | * The program should display both the input matrix and the transitive closure matrix. 320 | * 321 | * Input format: 322 | * The first line contains an integer n, representing the number of nodes, and an integer e, representing the number 323 | * of edges separated by a space. 324 | * 325 | * The next e lines contain three space-separated integers u, v, and w, where u and v are the nodes connected by an 326 | * edge with a weight w. 327 | * 328 | * Note: These edges are directed, and there can be multiple edges between the same pair of nodes. 329 | * 330 | * Output format: 331 | * The output displays the following format: 332 | * 333 | * The matrix of input data shows the initial edge weights between nodes. This matrix should be displayed with rows 334 | * and columns representing nodes and the elements of the matrix indicating the edge weights. 335 | * 336 | * The transitive closure matrix represents the shortest paths between all pairs of nodes. This matrix should also 337 | * be displayed with rows and columns representing nodes, and the elements of the matrix indicating the shortest 338 | * path lengths. 339 | * 340 | * Note: Rows and columns should be separated by tab space. 341 | * 342 | * Code constraints: 343 | * 344 | * The given test cases will fall under the following specifications: 345 | * 346 | * 1 ≤ n ≤ 10 347 | * 1 ≤ e ≤ 10 348 | * 1 ≤ u, v ≤ n 349 | * 1 ≤ w ≤ 999 350 | * 351 | * Sample Test Cases: 352 | * 353 | * Input 1: 354 | * 3 3 355 | * 1 2 10 356 | * 2 3 15 357 | * 3 1 12 358 | * 359 | * Output 1: 360 | * Matrix of input data 361 | * 999 10 999 362 | * 999 999 15 363 | * 12 999 999 364 | * 365 | * Transitive closure 366 | * 0 10 25 367 | * 27 0 15 368 | * 12 22 0 369 | * 370 | * Input 2: 371 | * 3 3 372 | * 1 2 4 373 | * 2 3 6 374 | * 1 3 10 375 | * 376 | * Output 2: 377 | * Matrix of input data 378 | * 999 4 10 379 | * 999 999 6 380 | * 999 999 999 381 | * 382 | * Transitive closure 383 | * 0 4 10 384 | * 999 0 6 385 | * 999 999 0 386 | */ 387 | 388 | 389 | 390 | import java.util.Scanner; 391 | 392 | class FloydWarshallAlgorithm { 393 | 394 | public static void floyds(int[][] p, int n) { 395 | int i, j, k; 396 | for (k = 1; k <= n; k++) { 397 | for (i = 1; i <= n; i++) { 398 | for (j = 1; j <= n; j++) { 399 | if (i == j) { 400 | p[i][j] = 0; 401 | } else { 402 | p[i][j] = min(p[i][j], p[i][k] + p[k][j]); 403 | } 404 | } 405 | } 406 | } 407 | } 408 | 409 | public static int min(int a, int b) { 410 | if (a < b) 411 | return a; 412 | else 413 | return b; 414 | } 415 | 416 | public static void main(String[] args) { 417 | Scanner scanner = new Scanner(System.in); 418 | 419 | int n, e, u, v, w; 420 | int[][] p = new int[11][11]; // Using 11 to handle 1-based index 421 | 422 | n = scanner.nextInt(); 423 | e = scanner.nextInt(); 424 | 425 | // Initialize matrix 426 | for (int i = 1; i <= n; i++) { 427 | for (int j = 1; j <= n; j++) { 428 | p[i][j] = 999; 429 | } 430 | } 431 | 432 | // Input edges 433 | for (int i = 1; i <= e; i++) { 434 | u = scanner.nextInt(); 435 | v = scanner.nextInt(); 436 | w = scanner.nextInt(); 437 | p[u][v] = w; 438 | } 439 | 440 | // Print matrix of input data 441 | System.out.println("Matrix of input data"); 442 | for (int i = 1; i <= n; i++) { 443 | for (int j = 1; j <= n; j++) { 444 | System.out.print(p[i][j] + "\t"); 445 | } 446 | System.out.println(); 447 | } 448 | 449 | floyds(p, n); 450 | 451 | // Print transitive closure 452 | System.out.println("Transitive closure "); 453 | for (int i = 1; i <= n; i++) { 454 | for (int j = 1; j <= n; j++) { 455 | System.out.print(p[i][j] + "\t"); 456 | } 457 | System.out.println(); 458 | } 459 | 460 | scanner.close(); 461 | } 462 | } 463 | 464 | 465 | -------------------------------------------------------------------------------- /Lab 6 - Binary Search Tree/Challenge Yourself.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * The task is to construct an Optimal Binary Search Tree (OBST) and calculate the cost matrix for the OBST, given a set of 5 | * keys, their frequencies, and the probabilities of unsuccessful searches. 6 | * 7 | * The goal is to calculate the cost matrix C, where each entry represents the cost of a subtree in the OBST. The cost of 8 | * a subtree is defined as the total frequency of all the keys in that subtree multiplied by the distance from the root of 9 | * that subtree to each key. 10 | * 11 | * Input format: 12 | * 13 | * The first line of input consists of an integer N, the number of keys in the tree. 14 | * 15 | * The second line consists of N space-separated integers, representing the keys. 16 | * 17 | * The third line consists of N space-separated integers, representing the frequencies of the corresponding keys. 18 | * 19 | * The fourth line consists of N+1 space-separated integers, representing the probabilities of unsuccessful searches. 20 | * 21 | * Output format: 22 | * 23 | * The output displays the cost matrix C, where C[i][j] represents the cost of the subtree rooted between keys[i] and keys[j]. 24 | * 25 | * Each row of the matrix should be printed on a new line, with elements separated by spaces. 26 | * 27 | * Code constraints: 28 | * 29 | * 1 ≤ N ≤ 10 30 | * 1 ≤ Keys, Frequencies, and Probabilities ≤ 1000 31 | * 32 | * Sample Test Case 1: 33 | * 34 | * Input: 35 | * 3 36 | * 10 20 30 37 | * 1 1 2 38 | * 1 2 1 2 39 | * 40 | * Output: 41 | * 1 7 14 25 42 | * 2 7 17 43 | * 1 8 44 | * 2 45 | * 46 | * Sample Test Case 2: 47 | * 48 | * Input: 49 | * 3 50 | * 10 20 30 51 | * 3 1 6 52 | * 1 2 3 4 53 | * 54 | * Output: 55 | * 1 9 22 46 56 | * 2 11 31 57 | * 3 20 58 | * 4 59 | * 60 | * Explanation: 61 | * The program needs to compute the OBST cost matrix based on the given keys, frequencies, and probabilities of unsuccessful 62 | * searches. Each entry in the cost matrix represents the cost of a subtree in the optimal binary search tree. 63 | */ 64 | 65 | 66 | import java.util.Scanner; 67 | 68 | interface OBSTOperations { 69 | void computeWCR(); 70 | } 71 | 72 | class OBST implements OBSTOperations { 73 | private static final int NMAX = 20; 74 | private int[][] C = new int[NMAX][NMAX]; 75 | private int[][] W = new int[NMAX][NMAX]; 76 | private int[][] R = new int[NMAX][NMAX]; 77 | private int[] q = new int[NMAX]; 78 | private int[] p = new int[NMAX]; 79 | private int[] keys = new int[NMAX]; 80 | private int numberOfKeys; 81 | 82 | public OBST(int numberOfKeys, int[] keys, int[] p, int[] q) { 83 | this.numberOfKeys = numberOfKeys; 84 | System.arraycopy(keys, 0, this.keys, 0, numberOfKeys + 1); 85 | System.arraycopy(p, 0, this.p, 0, numberOfKeys + 1); 86 | System.arraycopy(q, 0, this.q, 0, numberOfKeys + 1); 87 | } 88 | 89 | @Override 90 | public void computeWCR() { 91 | for (int i = 0; i <= numberOfKeys; i++) { 92 | W[i][i] = q[i]; 93 | for (int j = i + 1; j <= numberOfKeys; j++) { 94 | W[i][j] = W[i][j - 1] + p[j] + q[j]; 95 | } 96 | } 97 | 98 | for (int i = 0; i <= numberOfKeys; i++) { 99 | C[i][i] = W[i][i]; 100 | } 101 | 102 | for (int i = 0; i < numberOfKeys; i++) { 103 | int j = i + 1; 104 | C[i][j] = C[i][i] + C[j][j] + W[i][j]; 105 | R[i][j] = j; 106 | } 107 | 108 | for (int h = 2; h <= numberOfKeys; h++) { 109 | for (int i = 0; i <= numberOfKeys - h; i++) { 110 | int j = i + h; 111 | int m = R[i][j - 1]; 112 | int min = C[i][m - 1] + C[m][j]; 113 | for (int k = m + 1; k <= R[i + 1][j]; k++) { 114 | int x = C[i][k - 1] + C[k][j]; 115 | if (x < min) { 116 | m = k; 117 | min = x; 118 | } 119 | } 120 | C[i][j] = W[i][j] + min; 121 | R[i][j] = m; 122 | } 123 | } 124 | 125 | for (int i = 0; i <= numberOfKeys; i++) { 126 | for (int j = i; j <= numberOfKeys; j++) { 127 | System.out.print(C[i][j] + " "); 128 | } 129 | System.out.println(); 130 | } 131 | } 132 | } 133 | 134 | public class Main { 135 | public static void main(String[] args) { 136 | Scanner sc = new Scanner(System.in); 137 | int numberOfKeys = sc.nextInt(); 138 | int[] keys = new int[numberOfKeys + 1]; 139 | int[] p = new int[numberOfKeys + 1]; 140 | int[] q = new int[numberOfKeys + 1]; 141 | 142 | for (int i = 1; i <= numberOfKeys; i++) { 143 | keys[i] = sc.nextInt(); 144 | } 145 | for (int i = 1; i <= numberOfKeys; i++) { 146 | p[i] = sc.nextInt(); 147 | } 148 | for (int i = 0; i <= numberOfKeys; i++) { 149 | q[i] = sc.nextInt(); 150 | } 151 | 152 | OBST obst = new OBST(numberOfKeys, keys, p, q); 153 | obst.computeWCR(); 154 | } 155 | } 156 | 157 | 158 | /* 159 | * Problem Statement: 160 | * 161 | * Imagine you have a set of items, each with its popularity or frequency of use. 162 | * You want to organize these items to minimize the average search time. 163 | * This is similar to organizing a library where books are frequently borrowed, 164 | * so you want to arrange them to make finding books quick and efficient. 165 | * 166 | * Your task is to write a program that takes the probabilities of each item as input 167 | * and constructs an optimal binary search tree (OBST). The program should calculate 168 | * the minimum cost of constructing the OBST, which represents the average search time, 169 | * and determine the root of the constructed tree, which indicates the optimal starting 170 | * point for searching items. 171 | * 172 | * Create a program to find the minimum cost and root of OBST. 173 | * 174 | * Input format: 175 | * The first line consists of an integer n, representing the number of elements. 176 | * 177 | * The second line contains n space-separated integers representing the elements of the keys. 178 | * 179 | * The third line contains n+1 space-separated integers representing the probabilities. 180 | * 181 | * Output format: 182 | * The first line of output displays the Minimum cost of the OBST. 183 | * 184 | * The second line of output displays the root of the given OBST. 185 | * 186 | * Code constraints: 187 | * 1 ≤ n ≤ 10 188 | * 1 ≤ element, probability ≤ 103 189 | * 190 | * Sample test cases: 191 | * 192 | * Input 1: 193 | * 4 194 | * 3 3 1 1 195 | * 2 3 1 1 1 196 | * 197 | * Output 1: 198 | * Minimum cost = 32 199 | * Root = 2 200 | * 201 | * Input 2: 202 | * 2 203 | * 10 20 204 | * 1 2 2 205 | * 206 | * Output 2: 207 | * Minimum cost = 48 208 | * Root = 2 209 | */ 210 | 211 | 212 | import java.util.Scanner; 213 | 214 | interface OBSTOperations { 215 | void computeOptimalBST(); 216 | } 217 | 218 | class OBST implements OBSTOperations { 219 | private static final int MAX = 10; 220 | private int[][] W = new int[MAX][MAX]; 221 | private int[][] C = new int[MAX][MAX]; 222 | private int[][] R = new int[MAX][MAX]; 223 | private int[] p = new int[MAX]; 224 | private int[] q = new int[MAX]; 225 | private int numberOfKeys; 226 | 227 | public OBST(int numberOfKeys, int[] p, int[] q) { 228 | this.numberOfKeys = numberOfKeys; 229 | System.arraycopy(p, 0, this.p, 0, numberOfKeys + 1); 230 | System.arraycopy(q, 0, this.q, 0, numberOfKeys + 1); 231 | } 232 | 233 | @Override 234 | public void computeOptimalBST() { 235 | for (int i = 0; i <= numberOfKeys; i++) { 236 | for (int j = 0; j <= numberOfKeys; j++) { 237 | if (i == j) { 238 | W[i][j] = q[i]; 239 | C[i][j] = 0; 240 | R[i][j] = 0; 241 | } 242 | } 243 | } 244 | 245 | for (int b = 0; b < numberOfKeys; b++) { 246 | for (int i = 0, j = b + 1; j <= numberOfKeys; j++, i++) { 247 | if (i != j && i < j) { 248 | W[i][j] = p[j] + q[j] + W[i][j - 1]; 249 | int min = Integer.MAX_VALUE; 250 | int temp = 0; 251 | for (int k = i + 1; k <= j; k++) { 252 | int min1 = C[i][k - 1] + C[k][j] + W[i][j]; 253 | if (min > min1) { 254 | min = min1; 255 | temp = k; 256 | } 257 | } 258 | C[i][j] = min; 259 | R[i][j] = temp; 260 | } 261 | } 262 | } 263 | System.out.println("Minimum cost = " + C[0][numberOfKeys]); 264 | System.out.print("Root = " + R[0][numberOfKeys]); 265 | } 266 | } 267 | 268 | public class Main { 269 | public static void main(String[] args) { 270 | Scanner sc = new Scanner(System.in); 271 | int numberOfKeys = sc.nextInt(); 272 | int[] p = new int[numberOfKeys + 1]; 273 | int[] q = new int[numberOfKeys + 1]; 274 | 275 | for (int i = 1; i <= numberOfKeys; i++) { 276 | p[i] = sc.nextInt(); 277 | } 278 | for (int i = 0; i <= numberOfKeys; i++) { 279 | q[i] = sc.nextInt(); 280 | } 281 | 282 | OBST obst = new OBST(numberOfKeys, p, q); 283 | obst.computeOptimalBST(); 284 | } 285 | } 286 | 287 | 288 | /* 289 | * Problem Statement: 290 | * 291 | * Computer science students are exploring the concept of Optimal Binary Search Trees (OBSTs) and have been assigned a problem related to it. 292 | * 293 | * Your task is to develop a program that allows students to efficiently remove a key from an OBST and compute the updated cost of the OBST after deletion. 294 | * 295 | * An OBST is a binary search tree designed to minimize the average search time based on given key frequencies. 296 | * 297 | * Given a set of keys and their respective frequencies, implement a program that deletes a specified key from the OBST and determines the resulting cost of the tree. 298 | * 299 | * Input format: 300 | * - The first line contains an integer n, representing the number of keys in the OBST. 301 | * - The second line contains n space-separated integers, representing the keys in the OBST. 302 | * - The third line contains n space-separated integers, representing the frequencies of the corresponding keys. 303 | * - The fourth line contains an integer r, representing the key to be deleted from the OBST. 304 | * 305 | * Output format: 306 | * - The output displays one of the following: 307 | * 1. If the specified key is found in the OBST, output a single line containing the cost of the OBST after deleting the key. 308 | * 2. Otherwise, the output is "Key not found in the OBST." 309 | * 310 | * Code constraints: 311 | * - 1 <= n <= 10 312 | * - 1 <= keys <= 100 313 | * - 1 <= frequency <= 100 314 | * - 1 <= r <= 100 315 | * 316 | * Sample test cases: 317 | * Input 1: 318 | * 4 319 | * 10 12 20 9 320 | * 34 8 50 18 321 | * 9 322 | * 323 | * Output 1: 324 | * Cost of Optimal BST after deleting the key is 142 325 | * 326 | * Input 2: 327 | * 5 328 | * 10 20 30 40 50 329 | * 4 2 6 3 1 330 | * 60 331 | * 332 | * Output 2: 333 | * Key not found in the OBST. 334 | */ 335 | 336 | 337 | 338 | 339 | import java.util.Scanner; 340 | 341 | interface OBSTOperations { 342 | int computeOBST(int[] keys, int[] frequency, int n); 343 | int deleteKey(int[] keys, int[] frequency, int n, int keyToDelete); 344 | } 345 | 346 | class OBST implements OBSTOperations { 347 | private int sum(int[] frequency, int i, int j) { 348 | int s = 0; 349 | for (int k = i; k <= j; k++) { 350 | s += frequency[k]; 351 | } 352 | return s; 353 | } 354 | 355 | public int computeOBST(int[] keys, int[] frequency, int n) { 356 | int[][] cost = new int[n][n]; 357 | 358 | for (int i = 0; i < n; i++) { 359 | cost[i][i] = frequency[i]; 360 | } 361 | 362 | for (int chainLen = 2; chainLen <= n; chainLen++) { 363 | for (int i = 0; i <= n - chainLen; i++) { 364 | int j = i + chainLen - 1; 365 | cost[i][j] = Integer.MAX_VALUE; 366 | 367 | for (int r = i; r <= j; r++) { 368 | int leftCost = (r > i) ? cost[i][r - 1] : 0; 369 | int rightCost = (r < j) ? cost[r + 1][j] : 0; 370 | int currentCost = leftCost + rightCost + sum(frequency, i, j); 371 | 372 | if (currentCost < cost[i][j]) { 373 | cost[i][j] = currentCost; 374 | } 375 | } 376 | } 377 | } 378 | return cost[0][n - 1]; 379 | } 380 | 381 | public int deleteKey(int[] keys, int[] frequency, int n, int keyToDelete) { 382 | int keyIndex = -1; 383 | for (int i = 0; i < n; i++) { 384 | if (keys[i] == keyToDelete) { 385 | keyIndex = i; 386 | break; 387 | } 388 | } 389 | 390 | if (keyIndex == -1) { 391 | return Integer.MAX_VALUE; 392 | } 393 | 394 | for (int i = keyIndex; i < n - 1; i++) { 395 | keys[i] = keys[i + 1]; 396 | frequency[i] = frequency[i + 1]; 397 | } 398 | 399 | return computeOBST(keys, frequency, n - 1); 400 | } 401 | } 402 | 403 | public class Main { 404 | public static void main(String[] args) { 405 | Scanner sc = new Scanner(System.in); 406 | int n = sc.nextInt(); 407 | 408 | int[] keys = new int[n]; 409 | int[] frequency = new int[n]; 410 | 411 | for (int i = 0; i < n; i++) { 412 | keys[i] = sc.nextInt(); 413 | } 414 | 415 | for (int i = 0; i < n; i++) { 416 | frequency[i] = sc.nextInt(); 417 | } 418 | 419 | int keyToDelete = sc.nextInt(); 420 | OBST obst = new OBST(); 421 | int deletedCost = obst.deleteKey(keys, frequency, n, keyToDelete); 422 | 423 | if (deletedCost == Integer.MAX_VALUE) { 424 | System.out.println("Key not found in the OBST."); 425 | } else { 426 | System.out.println("Cost of Optimal BST after deleting the key is " + deletedCost); 427 | } 428 | } 429 | } 430 | 431 | 432 | -------------------------------------------------------------------------------- /Lab 6 - Binary Search Tree/Class Exercise.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * You are tasked with implementing a program that finds whether a given key exists in an Optimal Binary Search Tree (OBST) 5 | * using Dynamic programming. An OBST is a binary search tree that is constructed to minimize the average search time for 6 | * a set of keys with given frequencies. 7 | * 8 | * The objective is to determine if a specific key exists in the OBST based on the dynamic programming approach used to 9 | * construct the tree. 10 | * 11 | * Input format: 12 | * 13 | * The first line consists of an integer n, representing the number of keys and frequencies in the OBST. 14 | * 15 | * The next n lines contain two integers, key[i] and freq[i]. These represent the keys and their corresponding frequencies, 16 | * separated by a space. 17 | * 18 | * The last line consists of the integer m, representing the key Alice wants to search for in the OBST. 19 | * 20 | * Output format: 21 | * 22 | * The output should consist of a single line: 23 | * 24 | * - If the key is found in the OBST, print: "Key found in the OBST." 25 | * - If the key is not found in the OBST, print: "Key not found in the OBST." 26 | * 27 | * Code constraints: 28 | * 29 | * The given test cases fall under the following specifications: 30 | * 31 | * 1 ≤ n ≤ 10 32 | * 1 ≤ key[i] ≤ 100 33 | * 1 ≤ freq[i] ≤ 100 34 | * 1 ≤ m ≤ 100 35 | * 36 | * Sample Test Cases: 37 | * 38 | * Input 1: 39 | * 3 40 | * 1 3 41 | * 2 5 42 | * 3 7 43 | * 2 44 | * 45 | * Output 1: 46 | * Key 2 found in the OBST. 47 | * 48 | * Input 2: 49 | * 4 50 | * 3 9 51 | * 4 12 52 | * 5 8 53 | * 1 2 54 | * 2 55 | * 56 | * Output 2: 57 | * Key 2 not found in the OBST. 58 | */ 59 | 60 | 61 | // You are using Java 62 | import java.util.*; 63 | 64 | class Main1 { 65 | 66 | public static void main(String[] args) { 67 | Scanner sc = new Scanner(System.in); 68 | 69 | int n = sc.nextInt(); 70 | int[][] arr = new int[n][2]; 71 | 72 | for (int i = 0; i < n; i++) { 73 | arr[i][0] = sc.nextInt(); 74 | arr[i][1] = sc.nextInt(); 75 | } 76 | 77 | int m = sc.nextInt(); 78 | boolean flag = false; 79 | 80 | for (int[] a : arr) { 81 | if (a[0] == m && a[1] > 1) { 82 | System.out.print("key " + m + " found in the OBST."); 83 | flag = true; 84 | break; 85 | } 86 | } 87 | 88 | if (flag == false) { 89 | System.out.print("key " + m + " not found in the OBST."); 90 | } 91 | } 92 | } 93 | 94 | 95 | 96 | /* 97 | * Problem Statement: 98 | * 99 | * Alya is working on a project involving Optimal Binary Search Trees (OBSTs). OBSTs are data structures designed to minimize 100 | * the average search cost for a given set of keys and their corresponding frequencies. 101 | * 102 | * The task is to calculate the cost of the Optimal Binary Search Tree for a set of keys and their frequencies. The cost 103 | * is defined as the total weighted path length of the tree, where the path length of each node is multiplied by its 104 | * corresponding frequency. 105 | * 106 | * Input format: 107 | * 108 | * The first line of input consists of an integer n, representing the number of keys in the existing OBST. 109 | * 110 | * The second line of input consists of n space-separated integers, each representing a unique key K. 111 | * 112 | * The third line of input consists of n space-separated integers, each representing the frequency F of the corresponding key. 113 | * 114 | * Output format: 115 | * 116 | * The output should consist of a single line, which is the cost of the Optimal Binary Search Tree for the given set of 117 | * keys and frequencies. 118 | * 119 | * Code constraints: 120 | * 121 | * 1 ≤ n ≤ 10 122 | * 1 ≤ K, F ≤ 100 123 | * 124 | * Sample Test Case 1: 125 | * 126 | * Input: 127 | * 3 128 | * 10 12 20 129 | * 34 8 50 130 | * 131 | * Output: 132 | * Cost of Optimal BST is 142 133 | * 134 | * The program needs to calculate the optimal structure of the BST and return the associated cost based on the provided 135 | * keys and their respective frequencies. 136 | */ 137 | 138 | 139 | 140 | import java.util.*; 141 | 142 | interface OptimalBST { 143 | int findOptimalCost(int[] keys, int[] frequency, int n); 144 | } 145 | 146 | class OptimalBSTJava { 147 | public static void main(String[] args) { 148 | Scanner sc = new Scanner(System.in); 149 | int n = sc.nextInt(); 150 | int[] keys = new int[n]; 151 | int[] frequency = new int[n]; 152 | 153 | for (int i = 0; i < n; i++) { 154 | keys[i] = sc.nextInt(); 155 | } 156 | for (int i = 0; i < n; i++) { 157 | frequency[i] = sc.nextInt(); 158 | } 159 | 160 | OptimalBST bst = new OptimalBST() { 161 | public int findOptimalCost(int[] keys, int[] frequency, int n) { 162 | int[][] cost = new int[n][n]; 163 | 164 | for (int i = 0; i < n; i++) { 165 | cost[i][i] = frequency[i]; 166 | } 167 | 168 | for (int chainLen = 2; chainLen <= n; chainLen++) { 169 | for (int i = 0; i <= n - chainLen; i++) { 170 | int j = i + chainLen - 1; 171 | cost[i][j] = Integer.MAX_VALUE; 172 | 173 | for (int r = i; r <= j; r++) { 174 | int leftCost = (r > i) ? cost[i][r - 1] : 0; 175 | int rightCost = (r < j) ? cost[r + 1][j] : 0; 176 | int currentCost = leftCost + rightCost + sum(frequency, i, j); 177 | 178 | if (currentCost < cost[i][j]) { 179 | cost[i][j] = currentCost; 180 | } 181 | } 182 | } 183 | } 184 | return cost[0][n - 1]; 185 | } 186 | 187 | private int sum(int[] frequency, int i, int j) { 188 | int s = 0; 189 | for (int k = i; k <= j; k++) { 190 | s += frequency[k]; 191 | } 192 | return s; 193 | } 194 | }; 195 | 196 | System.out.println("Cost of Optimal BST is " + bst.findOptimalCost(keys, frequency, n)); 197 | } 198 | } 199 | 200 | 201 | -------------------------------------------------------------------------------- /Lab 6 - Binary Search Tree/Practice At Home.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * Imagine you're managing a warehouse where different items have varying demand frequencies. 5 | * Each item is like a key, and its demand frequency is like the frequency of access. 6 | * 7 | * Your goal is to organize the items in such a way that accessing them is as efficient as possible, 8 | * minimizing the total effort or cost required. 9 | * 10 | * For example, items that are frequently accessed together should be placed closer to each other for quicker access. 11 | * This is similar to constructing an optimal binary search tree, where the cost of accessing keys is minimized 12 | * by organizing them efficiently. 13 | * 14 | * The weight matrix W would then represent the total effort or cost of accessing items from one location to another in the warehouse. 15 | * This could be used to plan the layout of the warehouse to optimize access and minimize costs. 16 | * 17 | * Create a program to display the weight matrix of the OBST. 18 | * 19 | * Input format: 20 | * - The first line of input contains an integer N, representing the number of keys in the tree. 21 | * - The second line contains N integers, representing the keys themselves. 22 | * - The third line contains N integers, representing the frequencies of each key. 23 | * - The fourth line contains N + 1 integers, representing the probabilities of unsuccessful searches for each key and in-between keys. 24 | * 25 | * Output format: 26 | * - The program should output the weight matrix W where each row represents a starting key and each column represents an ending key. 27 | * 28 | * Code constraints: 29 | * - 1 ≤ N ≤ 10 30 | * - 1 ≤ Keys, Frequencies, Probabilities ≤ 100 31 | * 32 | * Sample test cases: 33 | * Input 1: 34 | * 2 35 | * 10 20 36 | * 1 1 37 | * 1 2 1 38 | * 39 | * Output 1: 40 | * 1 4 6 41 | * 2 4 42 | * 1 43 | * 44 | * Input 2: 45 | * 4 46 | * 10 20 30 40 47 | * 4 2 6 3 48 | * 2 3 1 5 6 49 | * 50 | * Output 2: 51 | * 2 9 12 23 32 52 | * 3 6 17 26 53 | * 1 12 21 54 | * 5 14 55 | * 6 56 | */ 57 | 58 | 59 | import java.util.Scanner; 60 | 61 | interface OBSTOperations { 62 | void computeW(); 63 | } 64 | 65 | class OBST implements OBSTOperations { 66 | private static final int NMAX = 20; 67 | private int[][] W = new int[NMAX][NMAX]; 68 | private int[] q = new int[NMAX]; // Unsuccessful searches 69 | private int[] p = new int[NMAX]; // Frequencies 70 | private int[] keys = new int[NMAX]; 71 | private int numberOfKeys; 72 | 73 | public OBST(int numberOfKeys, int[] keys, int[] p, int[] q) { 74 | this.numberOfKeys = numberOfKeys; 75 | System.arraycopy(keys, 0, this.keys, 0, numberOfKeys + 1); 76 | System.arraycopy(p, 0, this.p, 0, numberOfKeys + 1); 77 | System.arraycopy(q, 0, this.q, 0, numberOfKeys + 1); 78 | } 79 | 80 | @Override 81 | public void computeW() { 82 | for (int i = 0; i <= numberOfKeys; i++) { 83 | W[i][i] = q[i]; 84 | for (int j = i + 1; j <= numberOfKeys; j++) { 85 | W[i][j] = W[i][j - 1] + p[j] + q[j]; 86 | } 87 | } 88 | 89 | for (int i = 0; i <= numberOfKeys; i++) { 90 | for (int j = i; j <= numberOfKeys; j++) { 91 | System.out.print(W[i][j] + " "); 92 | } 93 | System.out.println(); 94 | } 95 | } 96 | } 97 | 98 | public class Main { 99 | public static void main(String[] args) { 100 | Scanner sc = new Scanner(System.in); 101 | int numberOfKeys = sc.nextInt(); 102 | int[] keys = new int[numberOfKeys + 1]; 103 | int[] p = new int[numberOfKeys + 1]; 104 | int[] q = new int[numberOfKeys + 1]; 105 | 106 | for (int i = 1; i <= numberOfKeys; i++) { 107 | keys[i] = sc.nextInt(); 108 | } 109 | for (int i = 1; i <= numberOfKeys; i++) { 110 | p[i] = sc.nextInt(); 111 | } 112 | for (int i = 0; i <= numberOfKeys; i++) { 113 | q[i] = sc.nextInt(); 114 | } 115 | 116 | OBST obst = new OBST(numberOfKeys, keys, p, q); 117 | obst.computeW(); 118 | } 119 | } 120 | 121 | 122 | 123 | /* 124 | * Problem Statement: 125 | * 126 | * Mansi, a dedicated and hardworking developer, is working on a project involving Optimal Binary Search Trees (OBSTs). 127 | * These specialized data structures help minimize the average search cost for a given set of keys and their associated frequencies. 128 | * 129 | * Her task is to design a program that computes the cost of an Optimal Binary Search Tree based on a given set of keys and their frequencies. 130 | * Assist her in building an efficient solution for this problem. 131 | * 132 | * Input format: 133 | * - The first line of input consists of an integer n, representing the number of keys in the existing OBST. 134 | * - The second line of input consists of n space-separated integers, each representing a unique key K. 135 | * - The third line of input consists of n space-separated integers, each representing the frequency F of the corresponding key. 136 | * 137 | * Output format: 138 | * - The output should consist of a single-line cost of the Optimal Binary Search Tree for the given set of keys and frequencies. 139 | * 140 | * Code constraints: 141 | * - 1 ≤ n ≤ 10 142 | * - 1 ≤ K, F ≤ 100 143 | * 144 | * Sample test cases: 145 | * Input 1: 146 | * 3 147 | * 10 12 20 148 | * 34 8 50 149 | * Output 1: 150 | * Cost of Optimal BST is 142 151 | * 152 | * Explanation: 153 | * In this problem, we need to calculate the cost of constructing an Optimal Binary Search Tree (OBST) using dynamic programming. 154 | * We will compute the minimum cost to search for a key in the tree while taking into account the frequencies of the keys. 155 | */ 156 | 157 | 158 | 159 | import java.util.*; 160 | 161 | interface OptimalBST { 162 | int findOptimalCost(int[] keys, int[] frequency, int n); 163 | } 164 | 165 | class OptimalBSTJava { 166 | public static void main(String[] args) { 167 | Scanner sc = new Scanner(System.in); 168 | int n = sc.nextInt(); 169 | int[] keys = new int[n]; 170 | int[] frequency = new int[n]; 171 | 172 | for (int i = 0; i < n; i++) { 173 | keys[i] = sc.nextInt(); 174 | } 175 | for (int i = 0; i < n; i++) { 176 | frequency[i] = sc.nextInt(); 177 | } 178 | 179 | OptimalBST bst = new OptimalBST() { 180 | public int findOptimalCost(int[] keys, int[] frequency, int n) { 181 | int[][] cost = new int[n][n]; 182 | 183 | for (int i = 0; i < n; i++) { 184 | cost[i][i] = frequency[i]; 185 | } 186 | 187 | for (int chainLen = 2; chainLen <= n; chainLen++) { 188 | for (int i = 0; i <= n - chainLen; i++) { 189 | int j = i + chainLen - 1; 190 | cost[i][j] = Integer.MAX_VALUE; 191 | 192 | for (int r = i; r <= j; r++) { 193 | int leftCost = (r > i) ? cost[i][r - 1] : 0; 194 | int rightCost = (r < j) ? cost[r + 1][j] : 0; 195 | int currentCost = leftCost + rightCost + sum(frequency, i, j); 196 | 197 | if (currentCost < cost[i][j]) { 198 | cost[i][j] = currentCost; 199 | } 200 | } 201 | } 202 | } 203 | return cost[0][n - 1]; 204 | } 205 | 206 | private int sum(int[] frequency, int i, int j) { 207 | int s = 0; 208 | for (int k = i; k <= j; k++) { 209 | s += frequency[k]; 210 | } 211 | return s; 212 | } 213 | }; 214 | 215 | System.out.println("Cost of Optimal BST is " + bst.findOptimalCost(keys, frequency, n)); 216 | } 217 | } 218 | 219 | 220 | /* 221 | * Problem Statement: 222 | * 223 | * Rohan, a passionate programmer, is working on optimizing search operations in databases. 224 | * His mentor has introduced him to Optimal Binary Search Trees (OBSTs)—a special type of binary search tree 225 | * designed to minimize the average search time for a set of keys with given frequencies. 226 | * 227 | * As part of his project, Rohan needs to develop a program that determines whether a given key exists in an OBST 228 | * using dynamic programming. Help him implement an efficient solution to achieve this task. 229 | * 230 | * Input format: 231 | * - The first line consists of an integer n, representing the number of keys and frequencies in the OBST. 232 | * - The next n lines contain two integers, key[i] and freq[i]. These represent the keys and their corresponding frequencies, separated by a space. 233 | * - The last line consists of the integer m, representing the key Rohan wants to search for in the OBST. 234 | * 235 | * Output format: 236 | * - If the key is found in the OBST, print "Key found in the OBST." 237 | * - If the key is not found in the OBST, print "Key not found in the OBST." 238 | * 239 | * Code constraints: 240 | * - 1 ≤ n ≤ 10 241 | * - 1 ≤ key[i] ≤ 100 242 | * - 1 ≤ freq[i] ≤ 100 243 | * - 1 ≤ m ≤ 100 244 | * 245 | * Sample test cases: 246 | * Input 1: 247 | * 3 248 | * 1 3 249 | * 2 5 250 | * 3 7 251 | * 2 252 | * Output 1: 253 | * Key 2 found in the OBST. 254 | * 255 | * Input 2: 256 | * 4 257 | * 3 9 258 | * 4 12 259 | * 5 8 260 | * 1 2 261 | * 2 262 | * Output 2: 263 | * Key 2 not found in the OBST. 264 | * 265 | * Explanation: 266 | * In this problem, we are tasked with searching for a key in the OBST. We are given the keys and their frequencies, 267 | * and we need to check if a particular key exists in the OBST or not. 268 | * The result is printed based on whether the key is present in the tree or not. 269 | */ 270 | 271 | 272 | 273 | import java.util.Scanner; 274 | 275 | interface OBSTOperations { 276 | boolean searchOBST(int[] keys, int[] freq, int n, int key); 277 | } 278 | 279 | class OBST implements OBSTOperations { 280 | @Override 281 | public boolean searchOBST(int[] keys, int[] freq, int n, int key) { 282 | int[][] cost = new int[n][n]; 283 | 284 | for (int i = 0; i < n; i++) { 285 | cost[i][i] = freq[i]; 286 | } 287 | 288 | for (int L = 2; L <= n; L++) { 289 | for (int i = 0; i <= n - L; i++) { 290 | int j = i + L - 1; 291 | cost[i][j] = Integer.MAX_VALUE; 292 | 293 | for (int r = i; r <= j; r++) { 294 | int c = ((r > i) ? cost[i][r - 1] : 0) + 295 | ((r < j) ? cost[r + 1][j] : 0) + 296 | (r < n ? freq[r] : 0); 297 | 298 | if (c < cost[i][j]) { 299 | cost[i][j] = c; 300 | } 301 | } 302 | } 303 | } 304 | 305 | int i = 0, j = n - 1; 306 | while (i <= j) { 307 | int mid = i + (j - i) / 2; 308 | if (keys[mid] == key) { 309 | return true; 310 | } else if (keys[mid] < key) { 311 | i = mid + 1; 312 | } else { 313 | j = mid - 1; 314 | } 315 | } 316 | return false; 317 | } 318 | } 319 | 320 | public class Main { 321 | public static void main(String[] args) { 322 | Scanner sc = new Scanner(System.in); 323 | int n = sc.nextInt(); 324 | 325 | int[] keys = new int[n]; 326 | int[] freq = new int[n]; 327 | 328 | for (int i = 0; i < n; i++) { 329 | keys[i] = sc.nextInt(); 330 | freq[i] = sc.nextInt(); 331 | } 332 | 333 | int keyToFind = sc.nextInt(); 334 | OBST obst = new OBST(); 335 | boolean result = obst.searchOBST(keys, freq, n, keyToFind); 336 | 337 | if (result) { 338 | System.out.println("Key " + keyToFind + " found in the OBST."); 339 | } else { 340 | System.out.println("Key " + keyToFind + " not found in the OBST."); 341 | } 342 | } 343 | } 344 | 345 | 346 | 347 | -------------------------------------------------------------------------------- /Lab 7 - 0/1 Knapsack/Challenge Yourself.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * Ragul is interested in solving the knapsack problem. He has a list of n items, each with a weight and a value. 5 | * Ragul wants to determine the maximum value he can obtain by selecting a combination of items to fit into his knapsack, which has a maximum weight capacity. 6 | * 7 | * Help Ragul write a program that calculates the following: 8 | * 9 | * 1. Calculate and print the sum of all n values. 10 | * 2. Calculate and print the average value of all n values with exactly 2 decimal places. 11 | * 3. Calculate and print the maximum value that can be obtained by selecting a combination of items to fit into the knapsack without exceeding its capacity. 12 | * 13 | * Note: Use the 0/1 knapsack (backtracking technique) method to solve the problem. 14 | * 15 | * Input format: 16 | * - The first line contains an integer n, the number of items. 17 | * - The next line contains n space-separated integers, the weights of the items. 18 | * - The next line contains n space-separated integers, the values of the items. 19 | * - The last line contains an integer C, the maximum weight capacity of the knapsack. 20 | * 21 | * Output format: 22 | * - The output consists of the following in each line: 23 | * 1. The sum of all n values as an integer. 24 | * 2. The average value of all n values with exactly 2 decimal places. 25 | * 3. The maximum value that can be obtained as an integer. 26 | * 27 | * Code constraints: 28 | * 1 ≤ n ≤ 10 29 | * 1 ≤ Weight of each item ≤ 100 30 | * 1 ≤ Value of each item ≤ 100 31 | * 1 ≤ C ≤ 30 32 | * 33 | * Sample test cases: 34 | * Input 1: 35 | * 3 36 | * 10 15 20 37 | * 45 65 70 38 | * 30 39 | * 40 | * Output 1: 41 | * Sum of values: 180 42 | * Average of values: 60.00 43 | * Maximum amount: 115 44 | * 45 | * Input 2: 46 | * 4 47 | * 3 4 5 6 48 | * 8 10 12 15 49 | * 12 50 | * 51 | * Output 2: 52 | * Sum of values: 45 53 | * Average of values: 11.25 54 | * Maximum amount: 30 55 | * 56 | * Explanation: 57 | * - We first compute the sum of values of the items. 58 | * - Then, we calculate the average of the values. 59 | * - Finally, we apply the 0/1 knapsack approach to determine the maximum value that can be obtained without exceeding the knapsack's weight limit. 60 | */ 61 | 62 | 63 | 64 | 65 | 66 | // You are using Java 67 | import java.util.Scanner; 68 | 69 | class KnapsackSolver { 70 | 71 | public static int max(int a, int b) { 72 | return (a > b) ? a : b; 73 | } 74 | 75 | public static int bruteForce(int[] w, int[] v, int n, int capacity) { 76 | int maxAmount = 0; 77 | int combinations = 1 << n; // Total possible combinations of items 78 | 79 | for (int i = 0; i < combinations; i++) { 80 | int currentWeight = 0; 81 | int currentAmount = 0; 82 | 83 | for (int j = 0; j < n; j++) { 84 | if ((i & (1 << j)) != 0) { 85 | currentWeight += w[j]; 86 | currentAmount += v[j]; 87 | } 88 | } 89 | 90 | if (currentWeight <= capacity) { 91 | maxAmount = max(maxAmount, currentAmount); 92 | } 93 | } 94 | 95 | return maxAmount; 96 | } 97 | 98 | public static void main(String[] args) { 99 | Scanner scanner = new Scanner(System.in); 100 | 101 | int n = scanner.nextInt(); 102 | int[] w = new int[n]; 103 | int[] v = new int[n]; 104 | 105 | for (int i = 0; i < n; i++) { 106 | w[i] = scanner.nextInt(); 107 | } 108 | 109 | for (int i = 0; i < n; i++) { 110 | v[i] = scanner.nextInt(); 111 | } 112 | 113 | int sum = 0; 114 | for (int value : v) { 115 | sum += value; 116 | } 117 | 118 | double average = (double)sum / n; 119 | 120 | System.out.println("Sum of values: " + sum); 121 | System.out.printf("Average of values: %.2f\n", average); 122 | 123 | int capacity = scanner.nextInt(); 124 | 125 | int maxAmount = bruteForce(w, v, n, capacity); 126 | System.out.println("Maximum amount: " + maxAmount); 127 | 128 | scanner.close(); 129 | } 130 | } 131 | 132 | 133 | /* 134 | * Problem Statement: 135 | * 136 | * A shipping company needs to load valuable cargo onto a limited-capacity ship. Each cargo item has: 137 | * 1. A weight (how heavy the item is). 138 | * 2. A value (the profit from shipping the item). 139 | * 140 | * The goal is to maximize the total value of the selected cargo while ensuring that the total weight does not exceed the ship's maximum capacity. 141 | * 142 | * The company wants an efficient algorithm using Branch and Bound to avoid unnecessary calculations and optimize cargo selection. 143 | * 144 | * Input format: 145 | * - The first line of input consists of an integer n, representing the number of cargo items. 146 | * - The second line of input consists of n space-separated integers, P, representing the value of each cargo item. 147 | * - The third line of input consists of n space-separated integers, C, representing the weight of each cargo item. 148 | * - The fourth line of input consists of an integer W, representing the ship’s maximum weight capacity. 149 | * 150 | * Output format: 151 | * - The output displays a single integer representing the maximum possible value that can be loaded onto the ship in the format: 152 | * "Maximum value: [maximum value]" 153 | * 154 | * Code constraints: 155 | * 1 ≤ n ≤ 15 156 | * 1 ≤ P, W ≤ 1000 157 | * 1 ≤ C ≤ 100 158 | * 159 | * Sample test cases: 160 | * Input 1: 161 | * 6 162 | * 300 150 120 100 90 80 163 | * 6 3 3 2 2 2 164 | * 10 165 | * 166 | * Output 1: 167 | * Maximum value: 490 168 | * 169 | * Input 2: 170 | * 5 171 | * 60 100 120 90 80 172 | * 10 20 30 40 50 173 | * 50 174 | * 175 | * Output 2: 176 | * Maximum value: 220 177 | * 178 | * Explanation: 179 | * - The shipping company is tasked with maximizing the value of the cargo they load onto the ship, considering both the value and weight constraints. 180 | * - The goal is to select the optimal set of cargo items that will maximize the total value without exceeding the maximum weight capacity of the ship. 181 | * - The solution can be implemented using a Branch and Bound approach to prune unnecessary calculations. 182 | */ 183 | 184 | 185 | 186 | 187 | import java.util.*; 188 | 189 | class Item { 190 | int weight, value; 191 | double ratio; 192 | 193 | public Item(int weight, int value) { 194 | this.weight = weight; 195 | this.value = value; 196 | this.ratio = (double) value / weight; 197 | } 198 | } 199 | 200 | // Node class for Branch and Bound Tree 201 | class Node { 202 | int level, profit, weight; 203 | double bound; 204 | 205 | public Node(int level, int profit, int weight, double bound) { 206 | this.level = level; 207 | this.profit = profit; 208 | this.weight = weight; 209 | this.bound = bound; 210 | } 211 | } 212 | 213 | class KnapsackBranchAndBound { 214 | 215 | // Function to calculate the upper bound of the profit in subtree 216 | static double bound(Node u, int n, int W, List arr) { 217 | if (u.weight >= W) return 0; 218 | 219 | double bound = u.profit; 220 | int j = u.level + 1; 221 | int totalWeight = u.weight; 222 | 223 | while (j < n && totalWeight + arr.get(j).weight <= W) { 224 | totalWeight += arr.get(j).weight; 225 | bound += arr.get(j).value; 226 | j++; 227 | } 228 | 229 | // If there's still remaining capacity, take fraction of next item 230 | if (j < n) { 231 | bound += (W - totalWeight) * arr.get(j).ratio; 232 | } 233 | 234 | return bound; 235 | } 236 | 237 | // Function to implement the branch and bound approach 238 | static int knapsack(int W, List arr, int n) { 239 | // Sort items by value/weight ratio in descending order 240 | arr.sort((a, b) -> Double.compare(b.ratio, a.ratio)); 241 | 242 | Queue queue = new LinkedList<>(); 243 | Node u, v; 244 | 245 | // Root node initialization 246 | u = new Node(-1, 0, 0, bound(new Node(-1, 0, 0, 0), n, W, arr)); 247 | int maxProfit = 0; 248 | 249 | queue.add(u); 250 | 251 | while (!queue.isEmpty()) { 252 | u = queue.poll(); 253 | 254 | if (u.level == n - 1) continue; // If all items considered, skip 255 | 256 | // Left child (Include item) 257 | v = new Node(u.level + 1, 258 | u.profit + arr.get(u.level + 1).value, 259 | u.weight + arr.get(u.level + 1).weight, 260 | 0); 261 | 262 | if (v.weight <= W && v.profit > maxProfit) 263 | maxProfit = v.profit; 264 | 265 | v.bound = bound(v, n, W, arr); 266 | if (v.bound > maxProfit) 267 | queue.add(v); 268 | 269 | // Right child (Exclude item) 270 | v = new Node(u.level + 1, u.profit, u.weight, 0); 271 | v.bound = bound(v, n, W, arr); 272 | 273 | if (v.bound > maxProfit) 274 | queue.add(v); 275 | } 276 | 277 | return maxProfit; 278 | } 279 | 280 | public static void main(String[] args) { 281 | Scanner sc = new Scanner(System.in); 282 | 283 | int n = sc.nextInt(); // Number of items 284 | List arr = new ArrayList<>(); 285 | 286 | int[] values = new int[n]; 287 | for (int i = 0; i < n; i++) { 288 | values[i] = sc.nextInt(); 289 | } 290 | 291 | for (int i = 0; i < n; i++) { 292 | int weight = sc.nextInt(); 293 | arr.add(new Item(weight, values[i])); 294 | } 295 | 296 | int W = sc.nextInt(); // Knapsack capacity 297 | 298 | int result = knapsack(W, arr, n); 299 | System.out.println("Maximum value: " + result); 300 | sc.close(); 301 | } 302 | } 303 | 304 | 305 | 306 | /* 307 | * Problem Statement: 308 | * 309 | * A courier company wants to load valuable packages into a delivery truck that has a weight limit. 310 | * Each package has a weight and a monetary value. The goal is to maximize the total value of the packages loaded into the truck 311 | * while ensuring that the total weight does not exceed the truck’s capacity. 312 | * 313 | * The company must decide which packages to include using a Branch and Bound approach to find the most profitable selection. 314 | * 315 | * Input format: 316 | * - The first line contains two integers n (the number of packages) and W (Maximum weight capacity of the truck), separated by a space. 317 | * - The second line contains n integers, representing the weights of the n packages separated by a space. 318 | * - The third line contains n integers, representing the values of the n packages separated by a space. 319 | * 320 | * Output format: 321 | * - The output prints a single integer representing the maximum total value that can be obtained within the weight limit. 322 | * 323 | * Code constraints: 324 | * 1 ≤ n ≤ 100 (Number of packages) 325 | * 1 ≤ W ≤ 1000 (Weight Capacity of the truck) 326 | * 1 ≤ weight of item ≤ 1000 (Weight of each package) 327 | * 1 ≤ value of item ≤ 1000 (Value of each package) 328 | * 329 | * Sample test cases: 330 | * Input 1: 331 | * 5 100 332 | * 10 20 30 40 50 333 | * 60 100 120 140 180 334 | * 335 | * Output 1: 336 | * 420 337 | * 338 | * Input 2: 339 | * 4 50 340 | * 2 8 12 20 341 | * 40 60 80 100 342 | * 343 | * Output 2: 344 | * 280 345 | * 346 | * Explanation: 347 | * - The courier company is tasked with maximizing the value of packages loaded into the truck, 348 | * considering both the value and weight constraints. 349 | * - The solution should be implemented using a Branch and Bound approach to find the most profitable selection of packages. 350 | */ 351 | 352 | 353 | 354 | 355 | import java.util.*; 356 | 357 | class Item { 358 | int weight, value, index; 359 | double ratio; 360 | 361 | public Item(int weight, int value, int index) { 362 | this.weight = weight; 363 | this.value = value; 364 | this.index = index; 365 | this.ratio = (double) value / weight; 366 | } 367 | } 368 | 369 | class Node { 370 | int level, profit, weight; 371 | double bound; 372 | 373 | public Node(int level, int profit, int weight, double bound) { 374 | this.level = level; 375 | this.profit = profit; 376 | this.weight = weight; 377 | this.bound = bound; 378 | } 379 | } 380 | 381 | class KnapsackBranchAndBound { 382 | 383 | // Comparator for sorting items based on value/weight ratio 384 | static class ItemComparator implements Comparator { 385 | public int compare(Item a, Item b) { 386 | return Double.compare(b.ratio, a.ratio); // Descending order 387 | } 388 | } 389 | 390 | // Function to compute upper bound for a node 391 | static double bound(Node u, int n, int W, List arr) { 392 | if (u.weight >= W) return 0; 393 | 394 | double bound = u.profit; 395 | int j = u.level + 1, totalWeight = u.weight; 396 | 397 | while (j < n && totalWeight + arr.get(j).weight <= W) { 398 | totalWeight += arr.get(j).weight; 399 | bound += arr.get(j).value; 400 | j++; 401 | } 402 | 403 | // If there's still remaining capacity, take fraction of the next item 404 | if (j < n) { 405 | bound += (W - totalWeight) * arr.get(j).ratio; 406 | } 407 | 408 | return bound; 409 | } 410 | 411 | // Function to solve 0/1 Knapsack using Branch and Bound 412 | static int knapsack(int n, int W, List arr) { 413 | // Sort items by value/weight ratio in descending order 414 | arr.sort(new ItemComparator()); 415 | 416 | Queue queue = new LinkedList<>(); 417 | Node u = new Node(-1, 0, 0, bound(new Node(-1, 0, 0, 0), n, W, arr)); 418 | int maxProfit = 0; 419 | 420 | queue.add(u); 421 | 422 | while (!queue.isEmpty()) { 423 | u = queue.poll(); 424 | 425 | if (u.level == n - 1) continue; 426 | 427 | // Left child (Include the item) 428 | Node v = new Node(u.level + 1, 429 | u.profit + arr.get(u.level + 1).value, 430 | u.weight + arr.get(u.level + 1).weight, 431 | 0); 432 | 433 | if (v.weight <= W && v.profit > maxProfit) { 434 | maxProfit = v.profit; 435 | } 436 | 437 | v.bound = bound(v, n, W, arr); 438 | if (v.bound > maxProfit) { 439 | queue.add(v); 440 | } 441 | 442 | // Right child (Exclude the item) 443 | v = new Node(u.level + 1, u.profit, u.weight, 0); 444 | v.bound = bound(v, n, W, arr); 445 | 446 | if (v.bound > maxProfit) { 447 | queue.add(v); 448 | } 449 | } 450 | 451 | return maxProfit; 452 | } 453 | 454 | public static void main(String[] args) { 455 | Scanner sc = new Scanner(System.in); 456 | 457 | int n = sc.nextInt(); // Number of items 458 | int W = sc.nextInt(); // Weight capacity 459 | 460 | List arr = new ArrayList<>(); 461 | 462 | int[] weights = new int[n]; 463 | for (int i = 0; i < n; i++) { 464 | weights[i] = sc.nextInt(); 465 | } 466 | 467 | for (int i = 0; i < n; i++) { 468 | int value = sc.nextInt(); 469 | arr.add(new Item(weights[i], value, i)); 470 | } 471 | 472 | int maxProfit = knapsack(n, W, arr); 473 | System.out.println(maxProfit); 474 | 475 | sc.close(); 476 | } 477 | } 478 | 479 | 480 | 481 | 482 | -------------------------------------------------------------------------------- /Lab 7 - 0/1 Knapsack/Class Exercise.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * Captain Aidan, a daring pirate, has discovered an ancient treasure cave filled with valuable relics. 5 | * However, the cave is protected by an ancient spell that limits the weight of the treasure he can carry. 6 | * Aidan has a magic knapsack with a maximum weight capacity of W. Inside the cave, he finds n different treasures, 7 | * each with a specific weight and value. 8 | * 9 | * Since he can only take each treasure once, Aidan must carefully choose which items to take to maximize 10 | * the total value without exceeding the weight limit of his knapsack. 11 | * 12 | * Help Captain Aidan pick the most valuable treasures while staying within the weight limit using branch and bound technique. 13 | * 14 | * Input format: 15 | * - The first line contains two integers n (the number of items) and W (the capacity of the knapsack), separated by a space. 16 | * - The second line contains n integers, where the i-th integer represents the weight of the i-th item. 17 | * - The third line contains n integers, where the i-th integer represents the value of the i-th item. 18 | * 19 | * Output format: 20 | * - The output prints the single integer representing the maximum value obtained by filling the knapsack with the given set of items. 21 | * 22 | * Code constraints: 23 | * - 1 ≤ n ≤ 100 (Number of items) 24 | * - 1 ≤ W ≤ 1000 (Capacity of the knapsack) 25 | * - 1 ≤ weight of item ≤ 1000 (Weight of each item) 26 | * - 1 ≤ value of item ≤ 1000 (Value of each item) 27 | * 28 | * Sample test cases: 29 | * Input 1: 30 | * 5 60 31 | * 10 20 30 40 50 32 | * 60 100 120 140 180 33 | * Output 1: 34 | * 280 35 | * 36 | * Input 2: 37 | * 4 30 38 | * 2 8 12 20 39 | * 40 60 80 100 40 | * Output 2: 41 | * 200 42 | * 43 | * Explanation: 44 | * The goal is to maximize the value in the knapsack while ensuring that the weight of the selected items 45 | * doesn't exceed the given weight capacity W. 46 | * We will use the branch and bound technique to explore potential item selections and prune the search tree 47 | * when it is guaranteed that no better solution can be found along that path. 48 | */ 49 | 50 | 51 | 52 | // You are using Java 53 | import java.util.*; 54 | 55 | public class Main { 56 | public static void main(String args[]) { 57 | Scanner sc = new Scanner(System.in); 58 | int n = sc.nextInt(); 59 | int W = sc.nextInt(); 60 | int wt[] = new int[n]; 61 | int val[] = new int[n]; 62 | 63 | for (int i = 0; i < n; i++) 64 | wt[i] = sc.nextInt(); 65 | 66 | for (int i = 0; i < n; i++) 67 | val[i] = sc.nextInt(); 68 | 69 | //int W = sc.nextInt(); 70 | 71 | System.out.println(helper(0, n, W, wt, val)); 72 | } 73 | 74 | public static int helper(int i, int n, int W, int wt[], int val[]) { 75 | if (i >= n) 76 | return 0; 77 | 78 | int include = 0; 79 | if (wt[i] <= W) 80 | include += helper(i + 1, n, W - wt[i], wt, val) + val[i]; 81 | int exclude = helper(i + 1, n, W, wt, val); 82 | 83 | return Math.max(include, exclude); 84 | } 85 | } 86 | 87 | 88 | /* 89 | * Problem Statement: 90 | * 91 | * Raju is a professional hiker preparing for a long trekking expedition. He has a backpack that can hold a maximum weight of W kilograms. 92 | * There are N essential items you want to carry, each with a specific weight and importance value (utility score). 93 | * His goal is to maximize the total importance value of the items you take while ensuring that the total weight does not exceed the backpack's capacity. 94 | * 95 | * He can either include or exclude each item—meaning he cannot take fractions of an item (e.g., you cannot take half of a tent). 96 | * Given the weights and importance values of the items, determine the maximum possible importance value he can carry in his backpack. 97 | * Help him to achieve his task using the backtracking technique. 98 | * 99 | * Input format: 100 | * - The first line contains two integers, N (number of items) and W (maximum weight the backpack can carry). 101 | * - The second line contains N integers, representing the weights of the items. 102 | * - The third line contains N integers, representing the importance values of the items. 103 | * 104 | * Output format: 105 | * - The output prints a single integer, which is the maximum importance value that can be achieved without exceeding the weight limit. 106 | * 107 | * Code constraints: 108 | * - 1 ≤ N ≤ 20 109 | * - 1 ≤ W ≤ 105 110 | * - 1 ≤ weight of each item ≤ W 111 | * - 1 ≤ value of each item ≤ 104 112 | * 113 | * Sample test cases: 114 | * Input 1: 115 | * 4 5 116 | * 2 3 4 5 117 | * 3 4 5 6 118 | * Output 1: 119 | * 7 120 | * 121 | * Input 2: 122 | * 5 10 123 | * 2 3 4 5 6 124 | * 3 4 8 8 10 125 | * Output 2: 126 | * 18 127 | * 128 | * Explanation: 129 | * The goal is to maximize the importance value in the backpack while ensuring that the weight of the selected items 130 | * doesn't exceed the given weight capacity W. 131 | * We will use backtracking to explore different combinations of items to take, trying both the possibility of including 132 | * and excluding each item, and recursively checking which combination gives the maximum importance value without exceeding the weight limit. 133 | */ 134 | 135 | 136 | 137 | // You are using Java 138 | import java.util.*; 139 | 140 | public class Main { 141 | public static void main(String args[]) { 142 | Scanner sc = new Scanner(System.in); 143 | int n = sc.nextInt(); 144 | int W=sc.nextInt(); 145 | int wt[] = new int[n]; 146 | int val[] = new int[n]; 147 | 148 | for (int i = 0; i < n; i++) 149 | wt[i] = sc.nextInt(); 150 | 151 | for (int i = 0; i < n; i++) 152 | val[i] = sc.nextInt(); 153 | 154 | //int W = sc.nextInt(); 155 | 156 | System.out.println(helper(0, n, W, wt, val)); 157 | } 158 | 159 | public static int helper(int i, int n, int W, int wt[], int val[]) { 160 | if (i >= n) 161 | return 0; 162 | 163 | int include = 0; 164 | if (wt[i] <= W) 165 | include += helper(i + 1, n, W - wt[i], wt, val) + val[i]; 166 | int exclude = helper(i + 1, n, W, wt, val); 167 | 168 | return Math.max(include, exclude); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /Lab 7 - 0/1 Knapsack/Practice At Home.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Problem Statement: 3 | * 4 | * A warehouse manager needs to ship valuable items with a weight limit on a transport vehicle. 5 | * Each item has: 6 | * - A weight (in kg). 7 | * - A value (profit earned by shipping the item). 8 | * 9 | * The goal is to maximize the total profit while ensuring that the total weight does not exceed the vehicle’s maximum capacity. 10 | * 11 | * The manager decides to use a branch-and-bound approach to select items optimally. 12 | * 13 | * Input format: 14 | * - The first line contains a single integer N, representing the number of items available in the warehouse. 15 | * - The next N lines each contain two integers: weight[i] and value[i], where weight[i] is the weight of the item and value[i] is the value (profit) of the item. 16 | * - The next line contains a single integer W, representing the vehicle's maximum weight capacity. 17 | * 18 | * Output format: 19 | * - The output prints a single integer representing the maximum profit that can be achieved within the weight limit. 20 | * 21 | * Code constraints: 22 | * 1 ≤ N ≤ 1000 23 | * 1 ≤ weight[i] ≤ 1000 24 | * 1 ≤ value[i] ≤ 1000 25 | * 1 ≤ W ≤ 1000 26 | * 27 | * Sample test cases: 28 | * 29 | * Input 1: 30 | * 4 31 | * 4 70 32 | * 2 30 33 | * 1 20 34 | * 3 40 35 | * 6 36 | * 37 | * Output 1: 38 | * 100 39 | * 40 | * Input 2: 41 | * 3 42 | * 10 200 43 | * 15 250 44 | * 20 300 45 | * 10 46 | * 47 | * Output 2: 48 | * 200 49 | * 50 | * Explanation: 51 | * - The manager needs to choose the best combination of items that maximizes total profit without exceeding the weight limit. 52 | * - The branch-and-bound approach helps prune unnecessary paths and efficiently finds the optimal selection of items. 53 | */ 54 | 55 | 56 | import java.util.*; 57 | 58 | class Item { 59 | double weight; 60 | int value; 61 | double ratio; 62 | 63 | public Item(double weight, int value) { 64 | this.weight = weight; 65 | this.value = value; 66 | this.ratio = value / weight; 67 | } 68 | } 69 | 70 | class Node { 71 | int level, profit, bound; 72 | double weight; 73 | 74 | public Node(int level, int profit, double weight, int bound) { 75 | this.level = level; 76 | this.profit = profit; 77 | this.weight = weight; 78 | this.bound = bound; 79 | } 80 | } 81 | 82 | class KnapsackBranchAndBound { 83 | 84 | // Comparator for sorting items by value/weight ratio 85 | static class ItemComparator implements Comparator { 86 | public int compare(Item a, Item b) { 87 | return Double.compare(b.ratio, a.ratio); // Sort in descending order 88 | } 89 | } 90 | 91 | // Function to compute upper bound for a node 92 | static int bound(Node u, int n, int W, List arr) { 93 | if (u.weight >= W) return 0; 94 | 95 | int profitBound = u.profit; 96 | int j = u.level + 1; 97 | double totalWeight = u.weight; 98 | 99 | while (j < n && totalWeight + arr.get(j).weight <= W) { 100 | totalWeight += arr.get(j).weight; 101 | profitBound += arr.get(j).value; 102 | j++; 103 | } 104 | 105 | // If there's still remaining capacity, take fraction of the next item 106 | if (j < n) { 107 | profitBound += (W - totalWeight) * arr.get(j).ratio; 108 | } 109 | 110 | return profitBound; 111 | } 112 | 113 | // Function to solve 0/1 Knapsack using Branch and Bound 114 | static int knapsack(int W, List arr, int n) { 115 | // Sort items by value/weight ratio in descending order 116 | arr.sort(new ItemComparator()); 117 | 118 | Queue queue = new LinkedList<>(); 119 | Node u = new Node(-1, 0, 0, bound(new Node(-1, 0, 0, 0), n, W, arr)); 120 | int maxProfit = 0; 121 | 122 | queue.add(u); 123 | 124 | while (!queue.isEmpty()) { 125 | u = queue.poll(); 126 | 127 | if (u.level == n - 1) continue; 128 | 129 | // Left child (Include the item) 130 | Node v = new Node(u.level + 1, 131 | u.profit + arr.get(u.level + 1).value, 132 | u.weight + arr.get(u.level + 1).weight, 133 | 0); 134 | 135 | if (v.weight <= W && v.profit > maxProfit) { 136 | maxProfit = v.profit; 137 | } 138 | 139 | v.bound = bound(v, n, W, arr); 140 | if (v.bound > maxProfit) { 141 | queue.add(v); 142 | } 143 | 144 | // Right child (Exclude the item) 145 | v = new Node(u.level + 1, u.profit, u.weight, 0); 146 | v.bound = bound(v, n, W, arr); 147 | 148 | if (v.bound > maxProfit) { 149 | queue.add(v); 150 | } 151 | } 152 | 153 | return maxProfit; 154 | } 155 | 156 | public static void main(String[] args) { 157 | Scanner sc = new Scanner(System.in); 158 | 159 | int n = sc.nextInt(); // Number of items 160 | List arr = new ArrayList<>(); 161 | 162 | for (int i = 0; i < n; i++) { 163 | double weight = sc.nextDouble(); 164 | int value = sc.nextInt(); 165 | arr.add(new Item(weight, value)); 166 | } 167 | 168 | int W = sc.nextInt(); // Knapsack capacity 169 | 170 | int maxProfit = knapsack(W, arr, n); 171 | System.out.print(maxProfit); 172 | 173 | sc.close(); 174 | } 175 | } 176 | 177 | 178 | 179 | /* 180 | Problem Statement: 181 | 182 | Alex and a group of adventurous friends are setting off on a thrilling expedition to explore the mysterious Lost Valley, 183 | a hidden paradise filled with breathtaking landscapes and ancient ruins. However, they can only carry a limited amount 184 | of gear due to the challenging terrain. 185 | 186 | To make the most of their journey, Alex and the team need to carefully select which items to pack in their backpacks. 187 | Each item has a specific weight and value, and they must choose wisely to maximize the total value of their gear 188 | while staying within the weight limit. 189 | 190 | Help Alex and the team determine the best combination of items to take, ensuring they are well-equipped for their 191 | adventure without exceeding the carrying capacity using the backtracking technique. 192 | 193 | -------------------------- 194 | Input format: 195 | -------------------------- 196 | - The first line contains an integer n, representing the number of items available for selection. 197 | - The second line contains an integer limit, representing the maximum weight limit your group can carry in a bag. 198 | - The next n lines contain space-separated information for each item: 199 | - The name of the item is a string (without spaces). 200 | - The weight of the item. 201 | - The value of the item. 202 | 203 | -------------------------- 204 | Output format: 205 | -------------------------- 206 | - The first line of output displays "Total value: " followed by an integer representing the total value of the selected items. 207 | - The second line of output displays "Total weight: " followed by an integer representing the total weight of the selected items. 208 | 209 | -------------------------- 210 | Code constraints: 211 | -------------------------- 212 | - 1 ≤ n ≤ 8 213 | - 1 ≤ limit ≤ 1000 214 | - 1 ≤ string length ≤ 50 215 | - 1 ≤ weight ≤ 100 216 | - 1 ≤ value ≤ 10000 217 | 218 | -------------------------- 219 | Sample test cases: 220 | -------------------------- 221 | 222 | Input 1: 223 | 2 224 | 25 225 | Bag 10 250 226 | Note 15 430 227 | 228 | Output 1: 229 | Total value: 680 230 | Total weight: 25 231 | 232 | -------------------------- 233 | 234 | Input 2: 235 | 3 236 | 50 237 | Laptop 40 10000 238 | Bottle 10 250 239 | Sunglasses 15 430 240 | 241 | Output 2: 242 | Total value: 10250 243 | Total weight: 50 244 | 245 | */ 246 | 247 | 248 | 249 | // You are using Java 250 | // You are using Java 251 | import java.util.*; 252 | 253 | public class Main { 254 | static int maxVal = 0, maxWeight = 0; 255 | static List bestItems = new ArrayList<>(); 256 | 257 | static void knapsack(List items, int index, int remainingWeight, int currentValue, int currentWeight, List selectedItems) { 258 | if (index == items.size()) { 259 | if (currentValue > maxVal) { 260 | maxVal = currentValue; 261 | maxWeight = currentWeight; 262 | bestItems = new ArrayList<>(selectedItems); 263 | } 264 | return; 265 | } 266 | 267 | Item item = items.get(index); 268 | 269 | // Include the item if it fits 270 | if (remainingWeight >= item.weight) { 271 | selectedItems.add(item.name); 272 | knapsack(items, index + 1, remainingWeight - item.weight, currentValue + item.value, currentWeight + item.weight, selectedItems); 273 | selectedItems.remove(selectedItems.size() - 1); 274 | } 275 | 276 | // Exclude the item 277 | knapsack(items, index + 1, remainingWeight, currentValue, currentWeight, selectedItems); 278 | } 279 | 280 | public static void main(String[] args) { 281 | Scanner sc = new Scanner(System.in); 282 | int n = sc.nextInt(); 283 | int limit = sc.nextInt(); 284 | List items = new ArrayList<>(); 285 | 286 | for (int i = 0; i < n; i++) { 287 | String name = sc.next(); 288 | int weight = sc.nextInt(); 289 | int value = sc.nextInt(); 290 | items.add(new Item(name, weight, value)); 291 | } 292 | 293 | knapsack(items, 0, limit, 0, 0, new ArrayList<>()); 294 | 295 | System.out.println("Total value: " + maxVal); 296 | System.out.println("Total weight: " + maxWeight); 297 | 298 | sc.close(); 299 | } 300 | } 301 | 302 | class Item { 303 | String name; 304 | int weight, value; 305 | 306 | Item(String name, int weight, int value) { 307 | this.name = name; 308 | this.weight = weight; 309 | this.value = value; 310 | } 311 | } 312 | 313 | 314 | 315 | /* 316 | Problem Statement: 317 | 318 | Michael has been given an important task—developing a program to solve the classic 0/1 Knapsack Problem. 319 | His goal is to help users select the most valuable combination of items while staying within a specified weight limit. 320 | 321 | In this problem, each item has a value and a weight, and the objective is to maximize the total value 322 | without exceeding the given weight capacity. 323 | 324 | Michael's program should determine the maximum possible value that can be obtained by selecting the optimal set of items 325 | using the backtracking technique. 326 | 327 | -------------------------- 328 | Input format: 329 | -------------------------- 330 | - The first line of input consists of an integer n, representing the number of items available for selection. 331 | - The second line of input consists of n space-separated integers, P, which represent the values of the items. 332 | - The third line of input consists of n space-separated integers, C, which represent the weights of the corresponding items. 333 | - The fourth line of input consists of an integer W, representing the maximum weight limit of the knapsack. 334 | 335 | -------------------------- 336 | Output format: 337 | -------------------------- 338 | - The output displays the maximum value that can be obtained using the knapsack algorithm in the following format: 339 | "Maximum value: [maximum value]" 340 | 341 | -------------------------- 342 | Code constraints: 343 | -------------------------- 344 | - 1 ≤ n ≤ 15 345 | - 1 ≤ P, W ≤ 1000 346 | - 1 ≤ C ≤ 100 347 | 348 | -------------------------- 349 | Sample test cases: 350 | -------------------------- 351 | 352 | Input 1: 353 | 6 354 | 300 150 120 100 90 80 355 | 6 3 3 2 2 2 356 | 10 357 | 358 | Output 1: 359 | Maximum value: 490 360 | 361 | -------------------------- 362 | 363 | Input 2: 364 | 5 365 | 60 100 120 90 80 366 | 10 20 30 40 50 367 | 50 368 | 369 | Output 2: 370 | Maximum value: 220 371 | 372 | */ 373 | 374 | 375 | 376 | 377 | // You are using Java 378 | import java.util.*; 379 | 380 | public class Main { 381 | static int knapsack(int[] values, int[] weights, int capacity, int n, int index, int currentValue, int currentWeight) { 382 | if (index == n || currentWeight > capacity) 383 | return (currentWeight <= capacity) ? currentValue : 0; 384 | 385 | // Exclude current item 386 | int exclude = knapsack(values, weights, capacity, n, index + 1, currentValue, currentWeight); 387 | 388 | // Include current item if within weight limit 389 | int include = 0; 390 | if (currentWeight + weights[index] <= capacity) { 391 | include = knapsack(values, weights, capacity, n, index + 1, 392 | currentValue + values[index], currentWeight + weights[index]); 393 | } 394 | 395 | return Math.max(include, exclude); 396 | } 397 | 398 | public static void main(String[] args) { 399 | Scanner sc = new Scanner(System.in); 400 | int n = sc.nextInt(); 401 | int[] values = new int[n]; 402 | int[] weights = new int[n]; 403 | 404 | for (int i = 0; i < n; i++) values[i] = sc.nextInt(); 405 | for (int i = 0; i < n; i++) weights[i] = sc.nextInt(); 406 | int capacity = sc.nextInt(); 407 | 408 | int maxValue = knapsack(values, weights, capacity, n, 0, 0, 0); 409 | System.out.println("Maximum value: " + maxValue); 410 | 411 | sc.close(); 412 | } 413 | } 414 | 415 | 416 | 417 | 418 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Design and Analysis of Algorithms Lab 2 | 3 | Welcome to the **Design and Analysis of Algorithms Lab-NeoColab** repository! This collection contains structured lab work for learning and implementing core algorithmic concepts using Java. 4 | 5 | ## 📁 Repository Contents 6 | 7 | Each lab focuses on a different topic related to algorithms and data structures: 8 | 9 | | Sr. No. | Title | Description | 10 | |--------:|--------------------------------------|-----------------------------------------------------------| 11 | | Lab 0 |Base Codes | Contains the core logic implementations. | 12 | | Lab 1 | Prim's and Kruskal's | Implementation of Minimum Spanning Tree algorithms. | 13 | | Lab 2 | Strongly Connected Graph | Algorithms like Kosaraju's or Tarjan's for SCC detection. | 14 | | Lab 3 | Greedy & Dynamic Programming | Greedy and DP-based problem solving techniques. | 15 | | Lab 4 | Optimal Ordering | Solutions to sequencing and scheduling problems. | 16 | | Lab 5 | Shortest Path Algorithm | Dijkstra's and/or Bellman-Ford implementations. | 17 | | Lab 6 | Binary Search Tree | Implementation and traversal of BSTs. | 18 | | Lab 7 | 0/1 Knapsack | Solving the classic 0/1 Knapsack problem using backtracking.| 19 | | PDF | Concept Builder 1-7 | A compiled reference document with multiple-choice question (MCQ) to build conceptual understanding for Labs 1 to 7.| 20 | | Excel Sheet | Concept Builder - Practice | 200 multiple-choice question (MCQ) to practice more .| 21 | 22 | ## 🤝 Contributors 23 | 24 | - ![GitHub](https://img.shields.io/badge/GitHub-JoyForCode-blue?style=flat-square) [JoyForCode](https://github.com/JoyForCode) 25 | - ![GitHub](https://img.shields.io/badge/GitHub-Jain131102-blue?style=flat-square) [Jain131102](https://github.com/Jain131102) 26 | 27 | ## 📜 License 28 | 29 | This project is open-source and available under the ![MIT License](https://img.shields.io/badge/license-MIT-green?style=flat-square) [MIT License](https://opensource.org/licenses/MIT). 30 | Feel free to contribute by improving documentation, optimizing code, or adding new exercises! 31 | 32 | 33 | 34 | 35 | --------------------------------------------------------------------------------