📌  相关文章
📜  给定数组中最大路径总和,最多跳转K次

📅  最后修改于: 2021-05-14 08:25:37             🧑  作者: Mango

给定三个数组A,BC,每个数组均具有N个元素,任务是找到沿任何有效路径最多可具有K个跳跃的最大和。
如果路径具有以下属性,则该路径有效

  1. 它从数组的第0个索引开始。
  2. 它在数组的第(N-1)个索引处结束。
  3. 对于路径中索引为i的任何元素,下一个元素应仅在当前数组或相邻数组的索引i + 1上。
  4. 如果路径涉及从相邻数组中选择下一个(i + 1)元素,而不是当前元素,则称其为1跳

例子:

直观的贪婪方法(不正确):解决该问题的一种可能方法是在当前索引处选择最大元素,如果遗留了跳转,则从当前数组或相邻数组移至具有最大值的下一个索引。
例如:

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跳转
  • 同样,在阵列B上,
  • 同样,在数组C上,
  • 因此,最大和为:
  • 记忆:借助记忆可以降低上述递归解决方案的复杂性。
    • 计算后将结果存储在大小为[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)