Minimum sum of multiplications of n numbers


In this article, we will discuss two approaches to generate the desired sum. Both the approaches are dynamic programming-based approaches. In the first approach, we will memorization for dynamic programming and then we will apply the same approach for tabulation in order to avoid the use of extra stack space for recursion.

Problem Statement

We are given a list of n integers, and our goal is to minimize the sum of multiplications by repeatedly taking two adjacent numbers, summing them modulo 100, and replacing them in the list until only one number remains.

Let's consider the input [30, 40, 50] and calculate the minimum sum of multiplications.

To find the minimum sum, we'll explore different possibilities −

Case 1 − Take 30 and 40

Multiplication: 30 * 40 = 1200

And put back (30 + 40)%100= 70

After performing the operation, the list becomes: 70, 50

Multiplication Sum: 1200 + (70 * 50) = 4700

Case 2 − Take 40 and 50

Multiplication: 40 * 50 = 2000

And put back (40 + 50)%100 = 90

After performing the operation, the list becomes: 30, 90

Multiplication Sum: 2000 + (30 * 90) = 4700

Comparing the two cases, we see that the minimum sum of multiplications is 2000, which occurs in Case 2.

Therefore, the output is: 2000.

Approach 1

One approach is to solve this problem recursively, we can break it down into smaller parts and combine the results to find the optimal solution. We can define a 2D table, DP[iterator1][iterator2], where iterator1 and iterator2 represent the indices of the numbers in the range we are considering. The DP table will store the minimum sum of multiplications for multiplying the numbers from iterator1 to iterator2.

We will firstly apply memoization to this approach in order to neglect the overlapping subproblems.

Example

The dynamic programming approach to the problem is given below −

#include <bits/stdc++.h>
using namespace std;

long long DP[1000][1000];
long long mult_sum(  int nums[], int iterator, int iterator2){	
   long long sol = 0;
   for ( int i = iterator; i <= iterator2; i++ ){
      sol = (sol + nums[i]) % 100;
   }
   return sol;
}
long long solve(int nums[], int iterator, int iterator2){
   if (iterator == iterator2)
      return 0;
   if (DP[iterator][iterator2] != -1)
      return DP[iterator][iterator2];
      DP[iterator][iterator2] = INT_MAX;
   for (int k = iterator; k < iterator2; k++){
      DP[iterator][iterator2] = min(DP[iterator][iterator2], (solve(nums, iterator, k) +	solve(nums, k + 1, iterator2) +	(mult_sum(nums, iterator, k) * mult_sum(nums, k + 1, iterator2))));
   }
   return DP[iterator][iterator2];
}
int main() {
   int nums[] = { 30, 40, 50 };
   int n = sizeof(nums)/sizeof(nums[0]);
   for (int iterator = 0; iterator <= n ; iterator++)
      for (int iterator2 = 0; iterator2 <= n ; iterator2++)
         DP[iterator][iterator2] = -1;
      cout << "The sum of multiplication of the numbers according to the definition given in the problem is " << solve(nums, 0, n - 1) << endl;
   return 0;
}

Output

The sum of multiplication of the numbers according to the definition given in the problem is 4700

Approach 2

As we know, the memorization approach of dynamic programming needs an extra stack space for its execution, hence to reduce this space complexity, we can apply the same approach is top down manner i.e., tabulation method.

Example

The tabulation approach for the same problem discussed above is −

#include <bits/stdc++.h>
using namespace std;
long long mult_sum(int nums[], int iterator, int iterator2){	
   long long sol = 0;
   for (int it = iterator; it <= iterator2; it++){
      sol = (sol + nums[it]) % 100;
   }
   return sol;
}
long long min_sum_mult(int nums[], int n){
   long long store_dp[n][n];
   for (int iterator1 = 0; iterator1 < n; iterator1++) {
      for (int iterator2 = 0; iterator2 < n; iterator2++) {
         store_dp[iterator1][iterator2] = 0;
      }
   }
   for (int iterator1 = 2; iterator1 <= n; iterator1++) {
      for (int iterator2 = 0; iterator2 < n - iterator1 + 1; iterator2++) {
         int j = iterator2 + iterator1 - 1;
         store_dp[iterator2][j] = INT_MAX;
         for (int iterator3 = iterator2; iterator3 < j; iterator3++) {
            store_dp[iterator2][j] = min(store_dp[iterator2][j], (store_dp[iterator2][iterator3] +	store_dp[iterator3 + 1][j] +	(mult_sum(nums, iterator2, iterator3) * mult_sum(nums, iterator3 + 1, j))));
         }
      }
   }
   return store_dp[0][n - 1];
}
int main(){
   int nums[] = { 30, 40, 50 };
   int n = sizeof(nums)/sizeof(nums[0]);
   cout <<"The sum of multiplication of the numbers according to the definition given in the problem is "<< min_sum_mult(nums, n) << endl;
   return 0;
}

Output

The sum of multiplication of the numbers according to the definition given in the problem is 4700

Updated on: 05-Oct-2023

62 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements