给定三个相同大小 N 的数组A[] 、 B[]和C[] 。任务是在从这些数组中选择 N 个元素后最小化总和,使得在每个索引i处都有一个来自数组A[i 中任何一个的元素] 、 B[i]或C[i]可以选择,并且不能从同一个数组中选择两个连续的元素。
例子:
Input: A[] = {1, 100, 1}, B[] = {100, 100, 100}, C[] = {100, 100, 100}
Output: 102
A[0] + B[1] + A[2] = 1 + 100 + 100 = 201
A[0] + B[1] + C[2] = 1 + 100 + 100 = 201
A[0] + C[1] + B[2] = 1 + 100 + 100 = 201
A[0] + C[1] + A[2] = 1 + 100 + 1 = 102
B[0] + A[1] + B[2] = 100 + 100 + 100 = 300
B[0] + A[1] + C[2] = 100 + 100 + 100 = 300
B[0] + C[1] + A[2] = 100 + 100 + 1 = 201
B[0] + C[1] + B[2] = 100 + 100 + 100 = 300
C[0] + A[1] + B[2] = 100 + 100 + 100 = 300
C[0] + A[1] + C[2] = 100 + 100 + 100 = 300
C[0] + B[1] + A[2] = 100 + 100 + 1 = 201
C[0] + B[1] + C[2] = 100 + 100 + 100 = 300
Input: A[] = {1, 1, 1}, B[] = {1, 1, 1}, C[] = {1, 1, 1}
Output: 3
方法:问题是寻找最小成本的一个简单变体。额外的限制是,如果我们从特定数组中取出一个元素,那么我们不能从同一个数组中取出下一个元素。这可以使用递归轻松解决,但它的时间复杂度为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..
Javascript
52
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。