给定三个数组A,B和C,每个数组均具有N个元素,任务是找到沿任何有效路径最多可具有K个跳跃的最大和。
如果路径具有以下属性,则该路径有效:
- 它从数组的第0个索引开始。
- 它在数组的第(N-1)个索引处结束。
- 对于路径中索引为i的任何元素,下一个元素应仅在当前数组或相邻数组的索引i + 1上。
- 如果路径涉及从相邻数组中选择下一个(i + 1)元素,而不是当前元素,则称其为1跳
例子:
Input: A[] = {4, 5, 1, 2, 10}, B[] = {9, 7, 3, 20, 16}, C[] = {6, 12, 13, 9, 8}, K = 2
Output: 70
Explanation:
Starting from array B and selecting the elements as follows:
Select B[0]: 9 => sum = 9
Jump to C[1]: 12 => sum = 21
Select C[2]: 13 => sum = 34
Jump to B[3]: 20 => sum = 54
Select B[4]: 16 => sum = 70
Therefore maximum sum with at most 2 jumps = 70
Input: A[] = {10, 4, 1, 8}, B[] = {9, 0, 2, 5}, C[] = {6, 2, 7, 3}, K = 2
Output: 24
直观的贪婪方法(不正确):解决该问题的一种可能方法是在当前索引处选择最大元素,如果遗留了跳转,则从当前数组或相邻数组移至具有最大值的下一个索引。
例如:
Given,
A[] = {4, 5, 1, 2, 10},
B[] = {9, 7, 3, 20, 16},
C[] = {6, 12, 13, 9, 8},
K = 2
使用贪婪方法找到解决方案:
Current maximum: 9, K = 2, sum = 9
Next maximum: 12, K = 1, sum = 12
Next maximum: 13, K = 1, sum = 25
Next maximum: 20, K = 0, sum = 45
Adding rest of elements: 16, K = 0, sum = 61
Clearly, this is not the maximum sum.
因此,这种方法是不正确的。
动态编程方法:DP可以分为两个步骤使用-递归和记忆。
- 递归:使用以下递归关系可以解决此问题:
- 在数组A上,索引i与K跳转
pathSum(A, i, k) = A[i] + max(pathSum(A, i+1, k), pathSum(B, i+1, k-1));
- 同样,在阵列B上,
pathSum(B, i, k) = B[i] + max(pathSum(B, i+1, k), max(pathSum(A, i+1, k-1), pathSum(C, i+1, k-1));
- 同样,在数组C上,
pathSum(C, i, k) = C[i] + max(pathSum(C, i+1, k), pathSum(B, i+1, k-1));
- 因此,最大和为:
maxSum = max(pathSum(A, i, k), max(pathSum(B, i, k), pathSum(C, i, k)));
- 记忆:借助记忆可以降低上述递归解决方案的复杂性。
- 计算后将结果存储在大小为[3] [N] [K]的3维数组(dp)中。
- dp数组的任何元素的值存储第i个索引的最大和,其中x跳转到数组中
下面是该方法的实现:
C++
// C++ program to maximum path sum in
// the given arrays with at most K jumps
#include
using namespace std;
#define M 3
#define N 5
#define K 2
int dp[M][N][K];
void initializeDp()
{
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < K; k++)
dp[i][j][k] = -1;
}
// Function to calculate maximum path sum
int pathSum(int* a, int* b, int* c,
int i, int n,
int k, int on)
{
// Base Case
if (i == n)
return 0;
if (dp[on][i][k] != -1)
return dp[on][i][k];
int current, sum;
switch (on) {
case 0:
current = a[i];
break;
case 1:
current = b[i];
break;
case 2:
current = c[i];
break;
}
// No jumps available.
// Hence pathSum can be
// from current array only
if (k == 0) {
return dp[on][i][k]
= current
+ pathSum(a, b, c, i + 1,
n, k, on);
}
// Since jumps are available
// pathSum can be from current
// or adjacent array
switch (on) {
case 0:
sum = current
+ max(pathSum(a, b, c, i + 1,
n, k - 1, 1),
pathSum(a, b, c, i + 1,
n, k, 0));
break;
case 1:
sum = current
+ max(pathSum(a, b, c, i + 1,
n, k - 1, 0),
max(pathSum(a, b, c, i + 1,
n, k, 1),
pathSum(a, b, c, i + 1,
n, k - 1, 2)));
break;
case 2:
sum = current
+ max(pathSum(a, b, c, i + 1,
n, k - 1, 1),
pathSum(a, b, c, i + 1,
n, k, 2));
break;
}
return dp[on][i][k] = sum;
}
void findMaxSum(int* a, int* b,
int* c, int n, int k)
{
int sum = 0;
// Creating the DP array for memorisation
initializeDp();
// Find the pathSum using recursive approach
for (int i = 0; i < 3; i++) {
// Maximise the sum
sum = max(sum,
pathSum(a, b, c, 0,
n, k, i));
}
cout << sum;
}
// Driver Code
int main()
{
int n = 5, k = 1;
int A[n] = { 4, 5, 1, 2, 10 };
int B[n] = { 9, 7, 3, 20, 16 };
int C[n] = { 6, 12, 13, 9, 8 };
findMaxSum(A, B, C, n, k);
return 0;
}
Java
// Java program to maximum path sum in
// the given arrays with at most K jumps
import java.util.*;
class GFG
{
static int M = 3;
static int N = 5;
static int K = 2;
static int dp[][][] = new int[M][N][K];
static void initializeDp()
{
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < K; k++)
dp[i][j][k] = -1;
}
// Function to calculate maximum path sum
static int pathSum(int a[], int b[], int c[],
int i, int n,
int k, int on)
{
// Base Case
if (i == n)
return 0;
if (dp[on][i][k] != -1)
return dp[on][i][k];
int current = 0, sum = 0;
switch (on) {
case 0:
current = a[i];
break;
case 1:
current = b[i];
break;
case 2:
current = c[i];
break;
}
// No jumps available.
// Hence pathSum can be
// from current array only
if (k == 0) {
return dp[on][i][k]
= current
+ pathSum(a, b, c, i + 1,
n, k, on);
}
// Since jumps are available
// pathSum can be from current
// or adjacent array
switch (on) {
case 0:
sum = current
+ Math.max(pathSum(a, b, c, i + 1,
n, k - 1, 1),
pathSum(a, b, c, i + 1,
n, k, 0));
break;
case 1:
sum = current
+ Math.max(pathSum(a, b, c, i + 1,
n, k - 1, 0),
Math.max(pathSum(a, b, c, i + 1,
n, k, 1),
pathSum(a, b, c, i + 1,
n, k - 1, 2)));
break;
case 2:
sum = current
+ Math.max(pathSum(a, b, c, i + 1,
n, k - 1, 1),
pathSum(a, b, c, i + 1,
n, k, 2));
break;
}
return dp[on][i][k] = sum;
}
static void findMaxSum(int a[], int b[],
int c[], int n, int k)
{
int sum = 0;
// Creating the DP array for memorisation
initializeDp();
// Find the pathSum using recursive approach
for (int i = 0; i < 3; i++) {
// Maximise the sum
sum = Math.max(sum,
pathSum(a, b, c, 0,
n, k, i));
}
System.out.print(sum);
}
// Driver Code
public static void main(String []args)
{
int n = 5, k = 1;
int A[] = { 4, 5, 1, 2, 10 };
int B[] = { 9, 7, 3, 20, 16 };
int C[] = { 6, 12, 13, 9, 8 };
findMaxSum(A, B, C, n, k);
}
}
// This code is contributed by chitranayal
Python
#Python3 program to maximum path sum in
#the given arrays with at most K jumps
M = 3
N = 5
K = 2
dp=[[[-1 for i in range(K)]
for i in range(N)]
for i in range(M)]
def initializeDp():
for i in range(M):
for j in range(N):
for k in range(K):
dp[i][j][k] = -1
#Function to calculate maximum path sum
def pathSum(a, b, c, i, n, k, on):
#Base Case
if (i == n):
return 0
if (dp[on][i][k] != -1):
return dp[on][i][k]
current, sum = 0, 0
if on == 0:
current = a[i]
#break
if on == 1:
current = b[i]
#break
if on == 2:
current = c[i]
#break
#No jumps available.
#Hence pathSum can be
#from current array only
if (k == 0):
dp[on][i][k] = current +
pathSum(a, b, c,
i + 1, n, k, on)
return dp[on][i][k]
#Since jumps are available
#pathSum can be from current
#or adjacent array
if on == 0:
sum = current + max(pathSum(a, b, c, i + 1,
n, k - 1, 1),
pathSum(a, b, c,
i + 1, n, k, 0))
#break
if on == 1:
sum = current + max(pathSum(a, b, c, i + 1,
n, k - 1, 0),
max(pathSum(a, b, c, i + 1,
n, k, 1),
pathSum(a, b, c, i + 1,
n, k - 1, 2)))
#break
if on == 2:
sum = current + max(pathSum(a, b, c, i + 1,
n, k - 1, 1),
pathSum(a, b, c, i + 1,
n, k, 2))
#break
dp[on][i][k] = sum
return sum
def findMaxSum(a, b, c, n, k):
sum = 0
#Creating the DP array for memorisation
initializeDp()
#Find the pathSum using recursive approach
for i in range(3):
#Maximise the sum
sum = max(sum, pathSum(a, b, c, 0, n, k, i))
print(sum)
#Driver Code
if __name__ == '__main__':
n = 5
k = 1
A = [4, 5, 1, 2, 10]
B = [9, 7, 3, 20, 16]
C = [6, 12, 13, 9, 8]
findMaxSum(A, B, C, n, k)
#This code is contributed by Mohit Kumar 29
C#
// C# program to maximum path sum in
// the given arrays with at most K jumps
using System;
class GFG{
static int M = 3;
static int N = 5;
static int K = 2;
static int [,,]dp = new int[M, N, K];
static void initializeDp()
{
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
for(int k = 0; k < K; k++)
dp[i, j, k] = -1;
}
// Function to calculate maximum path sum
static int pathSum(int []a, int []b, int []c,
int i, int n,
int k, int on)
{
// Base Case
if (i == n)
return 0;
if (dp[on, i, k] != -1)
return dp[on, i, k];
int current = 0, sum = 0;
switch (on)
{
case 0:
current = a[i];
break;
case 1:
current = b[i];
break;
case 2:
current = c[i];
break;
}
// No jumps available.
// Hence pathSum can be
// from current array only
if (k == 0)
{
return dp[on, i, k] = current +
pathSum(a, b, c, i + 1,
n, k, on);
}
// Since jumps are available
// pathSum can be from current
// or adjacent array
switch (on)
{
case 0:
sum = current + Math.Max(pathSum(a, b, c, i + 1,
n, k - 1, 1),
pathSum(a, b, c, i + 1,
n, k, 0));
break;
case 1:
sum = current + Math.Max(pathSum(a, b, c, i + 1,
n, k - 1, 0),
Math.Max(pathSum(a, b, c, i + 1,
n, k, 1),
pathSum(a, b, c, i + 1,
n, k - 1, 2)));
break;
case 2:
sum = current + Math.Max(pathSum(a, b, c, i + 1,
n, k - 1, 1),
pathSum(a, b, c, i + 1,
n, k, 2));
break;
}
return dp[on, i, k] = sum;
}
static void findMaxSum(int []a, int []b,
int []c, int n, int k)
{
int sum = 0;
// Creating the DP array for memorisation
initializeDp();
// Find the pathSum using recursive approach
for(int i = 0; i < 3; i++)
{
// Maximise the sum
sum = Math.Max(sum, pathSum(a, b, c, 0,
n, k, i));
}
Console.Write(sum);
}
// Driver Code
public static void Main(String []args)
{
int n = 5, k = 1;
int []A = { 4, 5, 1, 2, 10 };
int []B = { 9, 7, 3, 20, 16 };
int []C = { 6, 12, 13, 9, 8 };
findMaxSum(A, B, C, n, k);
}
}
// This code is contributed by gauravrajput1
67
时间复杂度: O(N * K)
辅助空间: O(N * K)