给定三个大小为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..
52