Maximum path sum for each position with jumps under divisibility condition

Given an array of n positive integers. Initially we are at first position. We can jump position y to position x if y divides x and y < x. The task is to print maximum sum path ending with every position x where 1 <= x <= n.

Here position is index plus one assuming indexes begin with 0.

Examples:

Input :  arr[] = {2, 3, 1, 4, 6, 5}
Output : 2 5 3 9 8 10
Maximum sum path ending with position 1 is 2.
For position 1, last position to visit is 1 only.
So maximum sum for position 1 = 2.

Maximum sum path ending with position 2 is 5.
For position 2, path can be jump from position 1 
to 2 as 1 divides 2.
So maximum sum for position 2 = 2 + 3 = 5.

For position 3, path can be jump from position 1 
to 3 as 1 divides 3.
So maximum sum for position 3 = 2 + 3 = 5.

For position 4, path can be jump from position 1
to 2 and 2 to 4.
So maximum sum for position 4 = 2 + 3 + 4 = 9.

For position 5, path can be jump from position 1 
to 5.
So maximum sum for position 5 = 2 + 6 = 8.

For position 6, path can be jump from position 
1 to 2 and 2 to 6 or 1 to 3 and 3 to 6.
But path 1 -> 2 -> 6 gives maximum sum for
position 6 = 2 + 3 + 5 = 10.

The idea is to use Dynamic Programming to solve this problem.

Create an 1-D array dp[] where each element dp[i] 
stores maximum sum path ending at index i (or 
position x where x = i+1) with divisible jumps.

The recurrence relation for dp[i] can be defined as:

dp[i] = max(dp[i], dp[divisor of i+1] + arr[i]) 

To find all the divisor of i+1, move from 1 
divisor to sqrt(i+1).

Below is C++ implementation of this approach:

// C++ program to print maximum path sum ending with
// each position x such that all path step positions
// divide x.
#include<bits/stdc++.h>
using namespace std;

void printMaxSum(int arr[], int n)
{
    // Create an array such that dp[i] stores maximum
    // path sum ending with i.
    int dp[n];
    memset(dp, 0, sizeof dp);

    // Calculating maximum sum path for each element.
    for (int i = 0; i < n; i++)
    {
        dp[i] = arr[i];

        // Finding previous step for arr[i]
        // Moving from 1 to sqrt(i+1) since all the
        // divisors are present from sqrt(i+1).
        int maxi = 0;
        for (int j=1; j<=sqrt(i+1); j++)
        {
            // Checking if j is divisor of i+1.
            if (((i + 1)%j == 0) && (i + 1) != j)
            {
                // Checking which divisor will provide
                // greater value.
                if (dp[j-1] > maxi)
                    maxi = dp[j-1];
                if (dp[(i+1)/j - 1] > maxi && j != 1)
                    maxi = dp[(i+1)/j - 1];
            }
        }

        dp[i] += maxi;
    }

    // Printing the answer (Maximum path sum ending
    // with every position i+1.
    for (int i = 0; i < n; i++)
        cout << dp[i] << " ";
}

// Driven Program
int main()
{
    int arr[] = { 2, 3, 1, 4, 6, 5 };
    int n = sizeof(arr)/sizeof(arr[0]);

    printMaxSum(arr, n);

    return 0;
}

Output:

2 5 3 9 8 10

Time Complexity: O(n*sqrt(n)).

This article is contributed by Anuj Chauhan. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

GATE CS Corner    Company Wise Coding Practice





Writing code in comment? Please use code.geeksforgeeks.org, generate link and share the link here.