📌  相关文章
📜  最小化成本以通过给定操作将阵列缩减为单个元素

📅  最后修改于: 2021-05-17 18:11:18             🧑  作者: Mango

给定一个由N个整数和一个整数K组成的数组a [] ,任务是通过选择任意一对连续的数组元素并将它们替换为(a [i] +一个第[i + 1])为成本K *(A [1] + A [1 + 1])。

例子:

天真的方法:
最简单的解决方案是针对每个索引将数组分为两个半部分,然后递归计算两个半部分的成本,最后增加它们各自的成本。

下面是上述方法的实现:

C++
// C++ Program to implement
// the above approach
#include 
using namespace std;
#define inf 10000009
  
// Function to combine the sum of the two halves
int Combine(int a[], int i, int j)
{
    int sum = 0;
  
    // Calculate the sum from i to j
    for (int l = i; l <= j; l++)
        sum += a[l];
  
    return sum;
}
  
// Function to minimize the cost to
// reduce the array to a single element
int minCost(int a[], int i, int j, int k)
{
    if (i >= j) 
    {
  
        // Base case
        // If n = 1 or n = 0
        return 0;
    }
  
    // Intialize cost to maximum value
    int best_cost = inf;
  
    // Iterate through all possible indices
    // and find the best index
    // to combine the subproblems
    for (int pos = i; pos < j; pos++)
    {
  
        // Compute left subproblem
        int left = minCost(a, i, pos, k);
  
        // Compute right subproblem
        int right = minCost(a, pos + 1, j, k);
  
        // Calculate the best cost
        best_cost = min(best_cost, left + right + 
                                   k * Combine(a, i, j));
    }
  
    // Return the answer
    return best_cost;
}
  
// Driver code
int main()
{
    int n = 4;
    int a[] = { 4, 5, 6, 7 };
    int k = 3;
  
    cout << minCost(a, 0, n - 1, k) << endl;
    return 0;
}
  
// This code is contributed by PrinciRaj1992


Java
// Java Program to implement
// the above approach
import java.io.*;
  
class GFG {
  
    static int inf = 10000009;
  
    // Function to minimize the cost to
    // reduce the array to a single element
    public static int minCost(int a[], int i,
                              int j, int k)
    {
        if (i >= j) {
  
            // Base case
            // If n = 1 or n = 0
            return 0;
        }
  
        // Intialize cost to maximum value
        int best_cost = inf;
  
        // Iterate through all possible indices
        // and find the best index
        // to combine the subproblems
        for (int pos = i; pos < j; pos++) {
  
            // Compute left subproblem
            int left = minCost(a, i, pos, k);
  
            // Compute right subproblem
            int right = minCost(a, pos + 1, j, k);
  
            // Calculate the best  cost
            best_cost = Math.min(
                best_cost,
                left + right + k * Combine(a, i, j));
        }
  
        // Return the answer
        return best_cost;
    }
  
    // Function to combine the sum of the two halves
    public static int Combine(int a[], int i, int j)
    {
        int sum = 0;
  
        // Calculate the sum from i to j
        for (int l = i; l <= j; l++)
            sum += a[l];
  
        return sum;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        int n = 4;
        int a[] = { 4, 5, 6, 7 };
        int k = 3;
  
        System.out.println(minCost(a, 0, n - 1, k));
    }
}


Python3
# Python3 Program to implement
# the above approach
inf = 10000009;
  
# Function to minimize the cost to
# reduce the array to a single element
def minCost(a, i, j, k):
    if (i >= j):
        
        # Base case
        # If n = 1 or n = 0
        return 0;
  
    # Intialize cost to maximum value
    best_cost = inf;
  
    # Iterate through all possible indices
    # and find the best index
    # to combine the subproblems
    for pos in range(i, j):
        
        # Compute left subproblem
        left = minCost(a, i, pos, k);
  
        # Compute right subproblem
        right = minCost(a, pos + 1, j, k);
  
        # Calculate the best cost
        best_cost = min(best_cost, 
                        left + right + 
                        k * Combine(a, i, j));
  
    # Return the answer
    return best_cost;
  
# Function to combine 
# the sum of the two halves
def Combine(a, i, j):
    sum = 0;
  
    # Calculate the sum from i to j
    for l in range(i, j + 1):
        sum += a[l];
  
    return sum;
  
# Driver code
if __name__ == '__main__':
    n = 4;
    a = [4, 5, 6, 7];
    k = 3;
  
    print(minCost(a, 0, n - 1, k));
  
# This code is contributed by Amit Katiyar


C#
// C# Program to implement
// the above approach
using System;
class GFG{
  
  static int inf = 10000009;
  
  // Function to minimize the cost to
  // reduce the array to a single element
  public static int minCost(int []a, int i,
                            int j, int k)
  {
    if (i >= j) 
    {
  
      // Base case
      // If n = 1 or n = 0
      return 0;
    }
  
    // Intialize cost to maximum value
    int best_cost = inf;
  
    // Iterate through all possible indices
    // and find the best index
    // to combine the subproblems
    for (int pos = i; pos < j; pos++)
    {
  
      // Compute left subproblem
      int left = minCost(a, i, pos, k);
  
      // Compute right subproblem
      int right = minCost(a, pos + 1, j, k);
  
      // Calculate the best  cost
      best_cost = Math.Min(best_cost,
                           left + right + 
                           k * Combine(a, i, j));
    }
  
    // Return the answer
    return best_cost;
  }
  
  // Function to combine the sum of the two halves
  public static int Combine(int []a, int i, int j)
  {
    int sum = 0;
  
    // Calculate the sum from i to j
    for (int l = i; l <= j; l++)
      sum += a[l];
  
    return sum;
  }
  
  // Driver code
  public static void Main(String[] args)
  {
    int n = 4;
    int []a = { 4, 5, 6, 7 };
    int k = 3;
  
    Console.WriteLine(minCost(a, 0, n - 1, k));
  }
}
  
// This code is contributed by Rohit_ranjan


C++
// C++ program for the above approach 
#include 
using namespace std;
  
int inf = 10000000; 
  
// Function to generate the cost using 
// Prefix Sum Array technique 
vector preprocess(vector a, int n) 
{ 
    vector p(n); 
    p[0] = a[0]; 
      
    for(int i = 1; i < n; i++) 
    {
        p[i] = p[i - 1] + a[i]; 
    }
    return p; 
}
  
// Function to combine the sum of the
// two subproblems 
int Combine(vector p, int i, int j) 
{ 
    if (i == 0) 
        return p[j]; 
    else
        return p[j] - p[i - 1]; 
} 
  
// Function to minimize the cost to 
// add the array elements to a single element 
int minCost(vector a, int i, int j, int k, 
            vector prefix, vector> dp) 
{ 
    if (i >= j) 
        return 0; 
  
    // Check if the value is 
    // already stored in the array 
    if (dp[i][j] != -1) 
        return dp[i][j]; 
  
    int best_cost = inf; 
    for(int pos = i; pos < j; pos++)
    { 
          
        // Compute left subproblem 
        int left = minCost(a, i, pos, 
                           k, prefix, dp); 
  
        // Compute left subproblem 
        int right = minCost(a, pos + 1, j, 
                            k, prefix, dp); 
  
        // Calculate minimum cost 
        best_cost = min(best_cost, left + right +
                       (k * Combine(prefix, i, j))); 
    } 
      
    // Store the answer to 
    // avoid recalculation 
    return dp[i][j] = best_cost; 
} 
  
// Driver code    
int main()
{
    int n = 4; 
  
    vector a = { 4, 5, 6, 7 }; 
  
    int k = 3; 
  
    // Initialise dp array 
    vector> dp;
    dp.resize(n + 1, vector(n + 1));
    for(int i = 0; i < n + 1; i++)
    {
        for(int j = 0; j < n + 1; j++)
        {
            dp[i][j] = -1;
        }
    }
  
    // Preprocessing the array 
    vector prefix = preprocess(a, n); 
      
    cout << minCost(a, 0, n - 1, k, prefix, dp)
         << endl;
  
    return 0;
}
  
// This code is contributed by divyeshrabadiya07


Java
// Java Program for the above approach
import java.util.*;
public class Main {
  
    static int inf = 10000000;
  
    // Function to minimize the cost to
    // add the array elements to a single element
    public static int minCost(int a[], int i, int j, int k,
                              int[] prefix, int[][] dp)
    {
        if (i >= j)
            return 0;
  
        // Check if the value is
        // already stored in the array
        if (dp[i][j] != -1)
            return dp[i][j];
  
        int best_cost = inf;
        for (int pos = i; pos < j; pos++) {
  
            // Compute left subproblem
            int left = minCost(a, i, pos, k, prefix, dp);
  
            // Compute left subproblem
            int right
                = minCost(a, pos + 1, j, k, prefix, dp);
  
            // Calculate minimum cost
            best_cost = Math.min(
                best_cost,
                left + right + (k * Combine(prefix, i, j)));
        }
  
        // Store the answer to
        // avoid recalculation
        return dp[i][j] = best_cost;
    }
  
    // Function to generate the cost using
    // Prefix Sum Array technique
    public static int[] preprocess(int[] a, int n)
    {
        int p[] = new int[n];
        p[0] = a[0];
        for (int i = 1; i < n; i++)
            p[i] = p[i - 1] + a[i];
        return p;
    }
  
    // Function to combine the sum of the two subproblems
    public static int Combine(int[] p, int i, int j)
    {
        if (i == 0)
            return p[j];
        else
            return p[j] - p[i - 1];
    }
  
    // Driver Code
    public static void main(String args[])
    {
        int n = 4;
  
        int a[] = { 4, 5, 6, 7 };
  
        int k = 3;
  
        // Initialise dp array
        int dp[][] = new int[n + 1][n + 1];
        for (int i[] : dp)
            Arrays.fill(i, -1);
  
        // Preprocessing the array
        int prefix[] = preprocess(a, n);
  
        System.out.println(
            minCost(a, 0, n - 1, k, prefix, dp));
    }
}


Python3
# Python3 program for the above approach
inf = 10000000
  
# Function to minimize the cost to
# add the array elements to a single element
def minCost(a, i, j, k, prefix, dp):
      
    if (i >= j):
        return 0
  
    # Check if the value is
    # already stored in the array
    if (dp[i][j] != -1):
        return dp[i][j]
  
    best_cost = inf
    for pos in range(i, j):
  
        # Compute left subproblem
        left = minCost(a, i, pos,
                       k, prefix, dp)
  
        # Compute left subproblem
        right = minCost(a, pos + 1, j, 
                        k, prefix, dp)
  
        # Calculate minimum cost
        best_cost = min(best_cost,
                        left + right + 
                          (k * Combine(prefix, i, j)))
  
    # Store the answer to
    # avoid recalculation
    dp[i][j] = best_cost
      
    return dp[i][j]
  
# Function to generate the cost using
# Prefix Sum Array technique
def preprocess(a, n):
      
    p = [0] * n
    p[0] = a[0]
      
    for i in range(1, n):
        p[i] = p[i - 1] + a[i]
          
    return p
  
# Function to combine the sum
# of the two subproblems
def Combine(p, i, j):
      
    if (i == 0):
        return p[j]
    else:
        return p[j] - p[i - 1]
  
# Driver Code
if __name__ == "__main__":
      
    n = 4
    a = [ 4, 5, 6, 7 ]
    k = 3
  
    # Initialise dp array
    dp = [[-1 for x in range (n + 1)]
              for y in range (n + 1)]
  
    # Preprocessing the array
    prefix = preprocess(a, n)
  
    print(minCost(a, 0, n - 1, k, prefix, dp))
  
# This code is contributed by chitranayal


C#
// C# Program for the above approach
using System;
class GFG{
  
  static int inf = 10000000;
  
  // Function to minimize the cost to
  // add the array elements to a single element
  public static int minCost(int []a, int i, int j, int k,
                            int[] prefix, int[,] dp)
  {
    if (i >= j)
      return 0;
  
    // Check if the value is
    // already stored in the array
    if (dp[i, j] != -1)
      return dp[i, j];
  
    int best_cost = inf;
    for (int pos = i; pos < j; pos++) 
    {
  
      // Compute left subproblem
      int left = minCost(a, i, pos, k, prefix, dp);
  
      // Compute left subproblem
      int right = minCost(a, pos + 1, j, 
                          k, prefix, dp);
  
      // Calculate minimum cost
      best_cost = Math.Min(best_cost, left + right + 
                          (k * Combine(prefix, i, j)));
    }
  
    // Store the answer to
    // avoid recalculation
    return dp[i, j] = best_cost;
  }
  
  // Function to generate the cost using
  // Prefix Sum Array technique
  public static int[] preprocess(int[] a, int n)
  {
    int []p = new int[n];
    p[0] = a[0];
    for (int i = 1; i < n; i++)
      p[i] = p[i - 1] + a[i];
    return p;
  }
  
  // Function to combine the sum of the two subproblems
  public static int Combine(int[] p, int i, int j)
  {
    if (i == 0)
      return p[j];
    else
      return p[j] - p[i - 1];
  }
  
  // Driver Code
  public static void Main(String []args)
  {
    int n = 4;
  
    int []a = { 4, 5, 6, 7 };
  
    int k = 3;
  
    // Initialise dp array
    int [,]dp = new int[n + 1, n + 1];
    for(int i = 0; i < n + 1; i++)
    {
      for (int j = 0; j < n + 1; j++)
      {
        dp[i, j] = -1;
      }
    }
    // Preprocessing the array
    int []prefix = preprocess(a, n);
  
    Console.WriteLine(minCost(a, 0, n - 1, k, 
                              prefix, dp));
  }
}
  
// This code is contributed by sapnasingh4991


输出:
132

时间复杂度: O(2 N )
辅助空间: O(1)

高效方法:为了优化上述方法,其思想是使用动态编程的概念。请按照以下步骤解决问题:

  • 初始化矩阵dp [] [] ,使dp [i] [j]存储从索引ij的和
  • 使用Prefix Sum技术计算sum(i,j)
  • 计算两个子问题的总和,并用最小值更新成本。
  • 存储在dp [] []中并返回。

下面是上述方法的实现:

C++

// C++ program for the above approach 
#include 
using namespace std;
  
int inf = 10000000; 
  
// Function to generate the cost using 
// Prefix Sum Array technique 
vector preprocess(vector a, int n) 
{ 
    vector p(n); 
    p[0] = a[0]; 
      
    for(int i = 1; i < n; i++) 
    {
        p[i] = p[i - 1] + a[i]; 
    }
    return p; 
}
  
// Function to combine the sum of the
// two subproblems 
int Combine(vector p, int i, int j) 
{ 
    if (i == 0) 
        return p[j]; 
    else
        return p[j] - p[i - 1]; 
} 
  
// Function to minimize the cost to 
// add the array elements to a single element 
int minCost(vector a, int i, int j, int k, 
            vector prefix, vector> dp) 
{ 
    if (i >= j) 
        return 0; 
  
    // Check if the value is 
    // already stored in the array 
    if (dp[i][j] != -1) 
        return dp[i][j]; 
  
    int best_cost = inf; 
    for(int pos = i; pos < j; pos++)
    { 
          
        // Compute left subproblem 
        int left = minCost(a, i, pos, 
                           k, prefix, dp); 
  
        // Compute left subproblem 
        int right = minCost(a, pos + 1, j, 
                            k, prefix, dp); 
  
        // Calculate minimum cost 
        best_cost = min(best_cost, left + right +
                       (k * Combine(prefix, i, j))); 
    } 
      
    // Store the answer to 
    // avoid recalculation 
    return dp[i][j] = best_cost; 
} 
  
// Driver code    
int main()
{
    int n = 4; 
  
    vector a = { 4, 5, 6, 7 }; 
  
    int k = 3; 
  
    // Initialise dp array 
    vector> dp;
    dp.resize(n + 1, vector(n + 1));
    for(int i = 0; i < n + 1; i++)
    {
        for(int j = 0; j < n + 1; j++)
        {
            dp[i][j] = -1;
        }
    }
  
    // Preprocessing the array 
    vector prefix = preprocess(a, n); 
      
    cout << minCost(a, 0, n - 1, k, prefix, dp)
         << endl;
  
    return 0;
}
  
// This code is contributed by divyeshrabadiya07

Java

// Java Program for the above approach
import java.util.*;
public class Main {
  
    static int inf = 10000000;
  
    // Function to minimize the cost to
    // add the array elements to a single element
    public static int minCost(int a[], int i, int j, int k,
                              int[] prefix, int[][] dp)
    {
        if (i >= j)
            return 0;
  
        // Check if the value is
        // already stored in the array
        if (dp[i][j] != -1)
            return dp[i][j];
  
        int best_cost = inf;
        for (int pos = i; pos < j; pos++) {
  
            // Compute left subproblem
            int left = minCost(a, i, pos, k, prefix, dp);
  
            // Compute left subproblem
            int right
                = minCost(a, pos + 1, j, k, prefix, dp);
  
            // Calculate minimum cost
            best_cost = Math.min(
                best_cost,
                left + right + (k * Combine(prefix, i, j)));
        }
  
        // Store the answer to
        // avoid recalculation
        return dp[i][j] = best_cost;
    }
  
    // Function to generate the cost using
    // Prefix Sum Array technique
    public static int[] preprocess(int[] a, int n)
    {
        int p[] = new int[n];
        p[0] = a[0];
        for (int i = 1; i < n; i++)
            p[i] = p[i - 1] + a[i];
        return p;
    }
  
    // Function to combine the sum of the two subproblems
    public static int Combine(int[] p, int i, int j)
    {
        if (i == 0)
            return p[j];
        else
            return p[j] - p[i - 1];
    }
  
    // Driver Code
    public static void main(String args[])
    {
        int n = 4;
  
        int a[] = { 4, 5, 6, 7 };
  
        int k = 3;
  
        // Initialise dp array
        int dp[][] = new int[n + 1][n + 1];
        for (int i[] : dp)
            Arrays.fill(i, -1);
  
        // Preprocessing the array
        int prefix[] = preprocess(a, n);
  
        System.out.println(
            minCost(a, 0, n - 1, k, prefix, dp));
    }
}

Python3

# Python3 program for the above approach
inf = 10000000
  
# Function to minimize the cost to
# add the array elements to a single element
def minCost(a, i, j, k, prefix, dp):
      
    if (i >= j):
        return 0
  
    # Check if the value is
    # already stored in the array
    if (dp[i][j] != -1):
        return dp[i][j]
  
    best_cost = inf
    for pos in range(i, j):
  
        # Compute left subproblem
        left = minCost(a, i, pos,
                       k, prefix, dp)
  
        # Compute left subproblem
        right = minCost(a, pos + 1, j, 
                        k, prefix, dp)
  
        # Calculate minimum cost
        best_cost = min(best_cost,
                        left + right + 
                          (k * Combine(prefix, i, j)))
  
    # Store the answer to
    # avoid recalculation
    dp[i][j] = best_cost
      
    return dp[i][j]
  
# Function to generate the cost using
# Prefix Sum Array technique
def preprocess(a, n):
      
    p = [0] * n
    p[0] = a[0]
      
    for i in range(1, n):
        p[i] = p[i - 1] + a[i]
          
    return p
  
# Function to combine the sum
# of the two subproblems
def Combine(p, i, j):
      
    if (i == 0):
        return p[j]
    else:
        return p[j] - p[i - 1]
  
# Driver Code
if __name__ == "__main__":
      
    n = 4
    a = [ 4, 5, 6, 7 ]
    k = 3
  
    # Initialise dp array
    dp = [[-1 for x in range (n + 1)]
              for y in range (n + 1)]
  
    # Preprocessing the array
    prefix = preprocess(a, n)
  
    print(minCost(a, 0, n - 1, k, prefix, dp))
  
# This code is contributed by chitranayal

C#

// C# Program for the above approach
using System;
class GFG{
  
  static int inf = 10000000;
  
  // Function to minimize the cost to
  // add the array elements to a single element
  public static int minCost(int []a, int i, int j, int k,
                            int[] prefix, int[,] dp)
  {
    if (i >= j)
      return 0;
  
    // Check if the value is
    // already stored in the array
    if (dp[i, j] != -1)
      return dp[i, j];
  
    int best_cost = inf;
    for (int pos = i; pos < j; pos++) 
    {
  
      // Compute left subproblem
      int left = minCost(a, i, pos, k, prefix, dp);
  
      // Compute left subproblem
      int right = minCost(a, pos + 1, j, 
                          k, prefix, dp);
  
      // Calculate minimum cost
      best_cost = Math.Min(best_cost, left + right + 
                          (k * Combine(prefix, i, j)));
    }
  
    // Store the answer to
    // avoid recalculation
    return dp[i, j] = best_cost;
  }
  
  // Function to generate the cost using
  // Prefix Sum Array technique
  public static int[] preprocess(int[] a, int n)
  {
    int []p = new int[n];
    p[0] = a[0];
    for (int i = 1; i < n; i++)
      p[i] = p[i - 1] + a[i];
    return p;
  }
  
  // Function to combine the sum of the two subproblems
  public static int Combine(int[] p, int i, int j)
  {
    if (i == 0)
      return p[j];
    else
      return p[j] - p[i - 1];
  }
  
  // Driver Code
  public static void Main(String []args)
  {
    int n = 4;
  
    int []a = { 4, 5, 6, 7 };
  
    int k = 3;
  
    // Initialise dp array
    int [,]dp = new int[n + 1, n + 1];
    for(int i = 0; i < n + 1; i++)
    {
      for (int j = 0; j < n + 1; j++)
      {
        dp[i, j] = -1;
      }
    }
    // Preprocessing the array
    int []prefix = preprocess(a, n);
  
    Console.WriteLine(minCost(a, 0, n - 1, k, 
                              prefix, dp));
  }
}
  
// This code is contributed by sapnasingh4991
输出:
132

时间复杂度: O(N 2 )
辅助空间: O(N 2 )