📜  n 个数字的最小乘法和

📅  最后修改于: 2021-09-17 06:52:09             🧑  作者: 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 initialize(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]);
    initialize(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 initialize(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;
        initialize(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 initialize(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)
    initialize(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 initialize(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;
        initialize(n);
        Console.WriteLine(solve(a, 0, n - 1));
         
    }
}
 
// This code is contributed by vt_m.


PHP


Javascript


输出:

2400

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程