Given a rod of length ‘N’ units. The rod can be cut into different sizes and each size has a cost associated with it. Determine the maximum cost obtained by cutting the rod and selling its pieces.

Note:

1. The sizes will range from 1 to ‘N’ and will be integers.

2. The sum of the pieces cut should be equal to ‘N’.

3. Consider 1-based indexing.

Detailed explanation ( Input/output format, Notes, Images )

Constraints:

1 <= T <= 50
1 <= N <= 100
1 <= A[i] <= 100

Where ‘T’ is the total number of test cases, ‘N’ denotes the length of the rod, and A[i] is the cost of sub-length.

Time limit: 1 sec.
Sample Input 1:
2
5
2 5 7 8 10
8
3 5 8 9 10 17 17 20
Sample Output 1:
12
24
Explanation of sample input 1:
Test case 1:

All possible partitions are:
1,1,1,1,1           max_cost=(2+2+2+2+2)=10
1,1,1,2             max_cost=(2+2+2+5)=11
1,1,3               max_cost=(2+2+7)=11
1,4                 max_cost=(2+8)=10
5                   max_cost=(10)=10
2,3                 max_cost=(5+7)=12
1,2,2               max _cost=(1+5+5)=12    

Clearly, if we cut the rod into lengths 1,2,2, or 2,3, we get the maximum cost which is 12.


Test case 2:

Possible partitions are:
1,1,1,1,1,1,1,1         max_cost=(3+3+3+3+3+3+3+3)=24
1,1,1,1,1,1,2           max_cost=(3+3+3+3+3+3+5)=23
1,1,1,1,2,2             max_cost=(3+3+3+3+5+5)=22
and so on….

If we cut the rod into 8 pieces of length 1, for each piece 3 adds up to the cost. Hence for 8 pieces, we get 8*3 = 24.
Sample Input 2:
1
6
3 5 6 7 10 12
Sample Output 2:
18

Approach - Bottom Up

  • Similarly make solution
public class Solution {
	public static int cutRod(int price[], int n) {
		// Write your code here.
		int[][] dp = new int[n][n+1];
 
		for (int i = 0; i <= n; i++)
			dp[0][i] = i*price[0];
 
		for (int i = 1; i < n; i++) {
			for (int j = 0; j <= n; j++) {
				int notTake = dp[i-1][j];
				int take = Integer.MIN_VALUE;
				int rodLength = i+1;
				if (rodLength <= j)
					take = price[i] + dp[i][j-rodLength];
				dp[i][j] = Math.max(take, notTake);
			}
		}
 
		return dp[n-1][n];
	}
}

Approach - Memoization

  • Convert the same to memoization
  • Reason why n+1 is because that is length so it can go till n so array length would be n+1
public class Solution {
	public static Integer[][] dp;
	public static int cutRod(int price[], int n) {
		// Write your code here
		dp = new Integer[n][n+1];
		return dfs(price, 0, n);
	}
 
	public static int dfs(int[] prices, int i, int remaining) {
		if (i == prices.length) return 0;
 
		if (dp[i][remaining] != null) return dp[i][remaining];
 
		int notTake = dfs(prices, i+1, remaining);
		int take = 0;
		if (i + 1 <= remaining)
			take = prices[i] + dfs(prices, i, remaining - (i+1));
 
		return dp[i][remaining] = Math.max(take,notTake);
	}
}

Approach - Recursion

  • there are 2 options either we can take or not if we take we add the price
  • Why take i + 1 is because array is 0 index while remaining is for the length
public class Solution {
	public static int cutRod(int price[], int n) {
		// Write your code here.
		return dfs(price, 0, n);
	}
 
	public static int dfs(int[] prices, int i, int remaining) {
		if (i == prices.length) return 0;
 
		int notTake = dfs(prices, i+1, remaining);
 
		int take = 0;
		if (i + 1 <= remaining)
			take = prices[i] + dfs(prices, i, remaining - (i+1));
 
		return Math.max(take,notTake);
	}
}