📌  相关文章
📜  从给定的三个数组中选择元素后,将总和最小化

📅  最后修改于: 2021-04-29 09:06:48             🧑  作者: Mango

给定三个大小为N的数组A []B []C [] ,任务是在从这些数组中选择N个元素之后使和最小化,以便在每个索引i处,从数组A [i中的任何一个元素中选择一个元素]B [i]C [i]可以选择,并且不能从同一数组中选择两个连续的元素。

例子:

方法:问题是寻找最低成本的简单变化。额外的约束是,如果我们从特定数组中获取一个元素,那么我们将无法从同一数组中获取下一个元素。使用递归可以很容易地解决这个问题,但是它会给时间带来O(3 ^ n)的复杂度,因为对于每个元素,我们都有三个数组作为选择。

为了提高时间复杂度,我们可以轻松地将预先计算的值存储在dp数组中。

由于每个索引都有三个数组可供选择,因此在这种情况下会出现三种情况:

  • 情况1:如果从第i个元素中选择了数组A [],那么我们为第(i + 1)个元素选择数组B []或数组C []。
  • 情况2:如果从第i个元素中选择了数组B [],那么我们为第(i + 1)个元素选择数组A []或数组C []。
  • 情况3:如果从第i个元素中选择了数组C [],那么我们为第(i + 1)个元素选择数组A []或数组B []。

可以使用递归来解决上述状态,并且可以将中间结果存储在dp数组中。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
  
#include 
using namespace std;
#define SIZE 3
const int N = 3;
  
// Function to return the minimized sum
int minSum(int A[], int B[], int C[], int i,
        int n, int curr, int dp[SIZE][N])
{
  
    // If all the indices have been used
    if (n <= 0)
        return 0;
  
    // If this value is pre-calculated
    // then return its value from dp array
    // instead of re-computing it
    if (dp[n][curr] != -1)
        return dp[n][curr];
  
    // Here curr is the array chosen
    // for the (i - 1)th element
    // 0 for A[], 1 for B[] and 2 for C[]
  
    // If A[i - 1] was chosen previously then
    // only B[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 0) {
        return dp[n][curr] 
                = min(B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp),
                      C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
    }
  
    // If B[i - 1] was chosen previously then
    // only A[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 1)
        return dp[n][curr] 
                = min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                      C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
  
    // If C[i - 1] was chosen previously then
    // only A[i] or B[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    return dp[n][curr] 
                = min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                      B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp));
}
  
// Driver code
int main()
{
    int A[] = { 1, 50, 1 };
    int B[] = { 50, 50, 50 };
    int C[] = { 50, 50, 50 };
  
    // Initialize the dp[][] array
    int dp[SIZE][N];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < N; j++)
            dp[i][j] = -1;
  
    // min(start with A[0], start with B[0], start with C[0])
    cout << min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp),
                min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp),
                    C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp)));
  
    return 0;
}


Java
// Java implementation of the above approach
import java.io.*;
  
class GFG 
{
  
static int SIZE = 3;
static int N = 3;
  
// Function to return the minimized sum
static int minSum(int A[], int B[], int C[], int i,
                    int n, int curr, int [][]dp)
{
  
    // If all the indices have been used
    if (n <= 0)
        return 0;
  
    // If this value is pre-calculated
    // then return its value from dp array
    // instead of re-computing it
    if (dp[n][curr] != -1)
        return dp[n][curr];
  
    // Here curr is the array chosen
    // for the (i - 1)th element
    // 0 for A[], 1 for B[] and 2 for C[]
  
    // If A[i - 1] was chosen previously then
    // only B[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 0) 
    {
        return dp[n][curr] 
                = Math.min(B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp),
                    C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
    }
  
    // If B[i - 1] was chosen previously then
    // only A[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 1)
        return dp[n][curr] 
                = Math.min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                    C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
  
    // If C[i - 1] was chosen previously then
    // only A[i] or B[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    return dp[n][curr] 
                = Math.min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                    B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp));
}
  
// Driver code
public static void main (String[] args) 
{
    int A[] = { 1, 50, 1 };
    int B[] = { 50, 50, 50 };
    int C[] = { 50, 50, 50 };
      
    // Initialize the dp[][] array
    int dp[][] = new int[SIZE][N];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < N; j++)
            dp[i][j] = -1;
      
    // min(start with A[0], start with B[0], start with C[0])
    System.out.println(Math.min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp),
                Math.min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp),
                    C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp))));
}
}
  
// This code is contributed by anuj_67..


Python3
# Python3 implementation of the above approach 
  
import numpy as np
  
SIZE = 3; 
N = 3; 
  
# Function to return the minimized sum 
def minSum(A, B, C, i, n, curr, dp) : 
  
    # If all the indices have been used 
    if (n <= 0) :
        return 0; 
  
    # If this value is pre-calculated 
    # then return its value from dp array 
    # instead of re-computing it 
    if (dp[n][curr] != -1) :
        return dp[n][curr]; 
  
    # Here curr is the array chosen 
    # for the (i - 1)th element 
    # 0 for A[], 1 for B[] and 2 for C[] 
  
    # If A[i - 1] was chosen previously then 
    # only B[i] or C[i] can chosen now 
    # choose the one which leads 
    # to the minimum sum 
    if (curr == 0) : 
        dp[n][curr] = min( B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp), 
        C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp)); 
        return dp[n][curr] 
      
  
    # If B[i - 1] was chosen previously then 
    # only A[i] or C[i] can chosen now 
    # choose the one which leads 
    # to the minimum sum 
    if (curr == 1) :
        dp[n][curr] = min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp), 
        C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp)); 
        return dp[n][curr]
  
    # If C[i - 1] was chosen previously then 
    # only A[i] or B[i] can chosen now 
    # choose the one which leads 
    # to the minimum sum 
    dp[n][curr] = min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp), 
    B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp)); 
      
    return dp[n][curr]
  
  
# Driver code 
if __name__ == "__main__" : 
  
    A = [ 1, 50, 1 ]; 
    B = [ 50, 50, 50 ]; 
    C = [ 50, 50, 50 ]; 
  
    # Initialize the dp[][] array 
    dp = np.zeros((SIZE,N)); 
      
    for i in range(SIZE) :
        for j in range(N) : 
            dp[i][j] = -1; 
  
    # min(start with A[0], start with B[0], start with C[0]) 
    print(min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp), 
                min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp), 
                C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp)))); 
  
# This code is contributed by AnkitRai01


C#
// C# implementation of the above approach
using System;
  
class GFG 
{
  
static int SIZE = 3;
static int N = 3;
  
// Function to return the minimized sum
static int minSum(int []A, int []B, int []C, int i,
                    int n, int curr, int [,]dp)
{
  
    // If all the indices have been used
    if (n <= 0)
        return 0;
  
    // If this value is pre-calculated
    // then return its value from dp array
    // instead of re-computing it
    if (dp[n,curr] != -1)
        return dp[n,curr];
  
    // Here curr is the array chosen
    // for the (i - 1)th element
    // 0 for A[], 1 for B[] and 2 for C[]
  
    // If A[i - 1] was chosen previously then
    // only B[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 0) 
    {
        return dp[n,curr] 
                = Math.Min(B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp),
                    C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
    }
  
    // If B[i - 1] was chosen previously then
    // only A[i] or C[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    if (curr == 1)
        return dp[n,curr] 
                = Math.Min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                    C[i] + minSum(A, B, C, i + 1, n - 1, 2, dp));
  
    // If C[i - 1] was chosen previously then
    // only A[i] or B[i] can chosen now
    // choose the one which leads
    // to the minimum sum
    return dp[n,curr] 
                = Math.Min(A[i] + minSum(A, B, C, i + 1, n - 1, 0, dp),
                    B[i] + minSum(A, B, C, i + 1, n - 1, 1, dp));
}
  
// Driver code
public static void Main () 
{
    int []A = { 1, 50, 1 };
    int []B = { 50, 50, 50 };
    int []C = { 50, 50, 50 };
      
    // Initialize the dp[][] array
    int [,]dp = new int[SIZE,N];
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < N; j++)
            dp[i,j] = -1;
      
    // min(start with A[0], start with B[0], start with C[0])
    Console.WriteLine(Math.Min(A[0] + minSum(A, B, C, 1, SIZE - 1, 0, dp),
                Math.Min(B[0] + minSum(A, B, C, 1, SIZE - 1, 1, dp),
                    C[0] + minSum(A, B, C, 1, SIZE - 1, 2, dp))));
}
}
  
// This code is contributed by anuj_67..


输出:
52