📜  n个数字的最小乘法和

📅  最后修改于: 2021-04-26 07:56:49             🧑  作者: Mango

给定n个整数。任务是通过一次取两个相邻的数字并将它们的和%放回100,直到剩下一个数字,来最小化所有数字的乘积和。

例子 :

Input : 40 60 20 
Output : 2400  
Explanation: There are two possible cases:
1st possibility: Take 40 and 60, so multiplication=2400
and put back (60+40) % 100 = 0, making it 0, 20.
Multiplying 0 and 20 we get 0 so 
multiplication = 2400+0 = 2400. Put back (0+20)%100 = 20. 
2nd possibility: take 60 and 20, so 60*20 = 1200,
put back (60+20)%100 = 80, making it [40, 80] 
multiply 40*80 to get 3200, so multiplication
sum = 1200+3200 = 4400. Put back (40+80)%100 = 20 

Input : 5 6 
Output : 30 
Explanation: Only possibility is 5*6=30 

方法:问题是矩阵链乘法动态规划的一种变体

想法是将N个数划分为k的每个可能值。递归求解较小的部分,然后相乘并存储最小值。由于我们将其划分为k个部分,因此对于每个DP i,j,我们将有k个分区i <= k

由于将重复许多子问题,因此我们使用备忘录将值存储在nXn矩阵中。

下面给出了上述方法的说明:

C++
// CPP program to find the 
// minimum sum of multiplication
// of n numbers
#include 
using namespace std;
  
// Used in recursive 
// memoized solution
long long dp[1000][1000];
  
// function to calculate the cumulative 
// sum from a[i] to a[j]
long long sum(int a[], int i, int j)
{     
    long long ans = 0;
    for (int m = i; m <= j; m++)     
        ans = (ans + a[m]) % 100;
    return ans;
}
  
long long solve(int a[], int i, int j)
{
    // base case 
    if (i == j)
        return 0; 
      
    // memoization, if the partition 
    // has been called before then 
    // return the stored value 
    if (dp[i][j] != -1)
        return dp[i][j];
      
    // store a max value 
    dp[i][j] = INT_MAX;
      
    // we break them into k partitions 
    for (int k = i; k < j; k++)
    {
        // store the min of the 
        // formula thus obtained
        dp[i][j] = min(dp[i][j], (solve(a, i, k) +
                              solve(a, k + 1, j) + 
              (sum(a, i, k) * sum(a, k + 1, j))));
    }
      
    // return the minimum 
    return dp[i][j];
}
  
void intialize(int n)
{
    for (int i = 0; i <= n; i++) 
        for (int j = 0; j <= n; j++)
            dp[i][j] = -1;     
}
  
// Driver code 
int main() {
    int a[] = {40, 60, 20}; 
    int n = sizeof(a) / sizeof(a[0]);
    intialize(n);
    cout << solve(a, 0, n - 1) << endl;
    return 0;
}


Java
// Java program to find the  
// minimum sum of multiplication
// of n numbers
import java.io.*;
import java.math.*;
  
  
class GFG
{
      
    // Used in recursive
    // memoized solution
    static long dp[][] = new long[1000][1000];
      
    // function to calculate the 
    // cumulative  sum from a[i] to a[j]
    static long sum(int a[], int i, int j)
    {     
        long ans = 0;
        for (int m = i; m <= j; m++)     
            ans = (ans + a[m]) % 100;
        return ans;
    }
      
    static long solve(int a[], int i, int j)
    {
        // base case 
        if (i == j)
            return 0; 
          
        // memoization, if the partition 
        // has been called before then 
        // return the stored value 
        if (dp[i][j] != -1)
            return dp[i][j];
          
        // store a max value 
        dp[i][j] = 100000000;
          
        // we break them into k partitions 
        for (int k = i; k < j; k++)
        {
            // store the min of the
            // formula thus obtained
            dp[i][j] = Math.min(dp[i][j], (solve(a, i, k) +
                                       solve(a, k + 1, j) + 
                        (sum(a, i, k) * sum(a, k + 1,j))));
        }
          
        // return the minimum 
        return dp[i][j];
    }
      
    static void intialize(int n)
    {
        for (int i = 0; i <= n; i++) 
            for (int j = 0; j <= n; j++)
                dp[i][j] = -1;     
    }
      
    // Driver code 
    public static void main(String args[]) 
    {
        int a[] = {40, 60, 20}; 
        int n = a.length;
        intialize(n);
        System.out.println(solve(a, 0, n - 1));
          
    }
}
  
/*This code is contributed by Nikita Tiwari.*/


Python3
# Python3 program to find the 
# minimum sum of multiplication 
# of n numbers 
  
import numpy as np
import sys
  
# Used in recursive 
# memoized solution 
dp = np.zeros((1000,1000)) 
  
# function to calculate the cumulative 
# sum from a[i] to a[j] 
def sum(a, i, j) :
          
    ans = 0
    for m in range(i, j + 1) : 
        ans = (ans + a[m]) % 100
          
    return ans
  
  
def solve(a, i, j) :
  
    # base case 
    if (i == j) : 
        return 0
      
    # memoization, if the partition 
    # has been called before then 
    # return the stored value 
    if (dp[i][j] != -1) :
                  
        return dp[i][j] 
      
    # store a max value 
    dp[i][j] = sys.maxsize
      
    # we break them into k partitions 
    for k in range(i, j) :
                  
        # store the min of the 
        # formula thus obtained 
        dp[i][j] = min(dp[i][j], (solve(a, i, k) + solve(a, k + 1, j) 
                                + (sum(a, i, k) * sum(a, k + 1, j)))) 
      
    # return the minimum 
    return dp[i][j]
  
  
def intialize(n) :
          
    for i in range(n + 1) :
        for j in range(n + 1) :
            dp[i][j] = -1    
  
#Driver code 
if __name__ == "__main__" :
          
    a = [40, 60, 20]
    n = len(a) 
    intialize(n)
    print(int(solve(a, 0, n - 1))) 
  
# This code is contributed by Ryuga


C#
// C# program to find the 
// minimum sum of multiplication 
// of n numbers
using System;
  
class GFG 
{
      
    // Used in recursive 
    // memoized solution
    static long [,]dp = new long[1000, 1000];
      
    // Function to calculate the cumulative 
    // sum from a[i] to a[j]
    static long sum(int []a, int i, int j)
    { 
        long ans = 0;
        for (int m = i; m <= j; m++) 
            ans = (ans + a[m]) % 100;
        return ans;
    }
      
    static long solve(int []a, int i, int j)
    {
        // base case 
        if (i == j)
            return 0; 
          
        // memoization, if the partition 
        // has been called before then 
        // return the stored value 
        if (dp[i, j] != -1)
            return dp[i, j];
          
        // store a max value 
        dp[i, j] = 100000000;
          
        // we break them into k partitions 
        for (int k = i; k < j; k++)
        {
            // store the min of the 
            // formula thus obtained
            dp[i, j] = Math.Min(dp[i, j], (solve(a, i, k) +
                                       solve(a, k + 1, j) + 
                       (sum(a, i, k) * sum(a, k + 1, j))));
        }
          
        // return the minimum 
        return dp[i, j];
    }
      
    static void intialize(int n)
    {
        for (int i = 0; i <= n; i++) 
            for (int j = 0; j <= n; j++)
                dp[i, j] = -1; 
    }
      
    // Driver code 
    public static void Main() 
    {
        int []a = {40, 60, 20}; 
        int n = a.Length;
        intialize(n);
        Console.WriteLine(solve(a, 0, n - 1));
          
    }
}
  
// This code is contributed by vt_m.


PHP


输出 :

2400

时间复杂度: O(n ^ 3)
辅助空间: O(n ^ 2)