Minimum sum subsequence such that at least one of every four consecutive elements is picked

Given an array arr[] of positive integers. The task is to find minimum sum subsequence from the array such that at least one value among all groups of four consecutive elements is picked.

Examples:

Input: arr[] = {1, 2, 3, 4, 5, 6, 7, 8}
Output: 6
6 is sum of output subsequence {1, 5}
Note that we have following subarrays of four
consecutive elements
{(1, 2, 3, 4), 
 (2, 3, 4, 5),
 (3, 4, 5, 6)
 (4, 5, 6, 7)
 (5, 6, 7, 8)}
Our subsequence {1, 5} has an element from
all above groups of four consecutive elements.
And this subsequence is minimum sum such
subsequence.

Input : arr[] = {1, 2, 3, 3, 4, 5, 6, 1}
Output : 4
The subsequence is {3, 1}. Here we consider
second three.

Input: arr[] = {1, 2, 3, 2, 1}
Output: 2
The subsequence can be {1, 1} or {2}

Input: arr[] = {6, 7, 8}
Output: 6

Input: arr[] = {6, 7}
Output: 6

The idea is similar to LIS problem. We store minimum sum subsequence ending with every element of arr[]. We finally return minimum of last four values.

dp[i] stores minimum sum subsequence (with at least
one of every four consecutive elements) of arr[0..i] 
such that arr[i] is part of the solution. Note that 
this may not be the best solution for subarray
arr[0..i].

We can recursively compute dp[i] using below formula
dp[i] = arr[i] + min(dp[i-1], dp[i-2], dp[i-3], dp[i-4])

Finally we return minimum of dp[n-1], dp[n-2], 
dp[n-4] and dp[n-3]

Below is C++ implementation of above idea.

// C++ program to find minimum sum subsequence
// of an array such that one of every four
// consecutive elements is picked.
#include <iostream>
using namespace std;

// Returns sum of minimum sum subsequence
// such that one of every four consecutive
// elements is picked from arr[].
int minSum(int arr[], int n)
{
    // dp[i] is going to store minimum sum
    // subsequence of arr[0..i] such that arr[i]
    // is part of the solution. Note that this
    // may not be the best solution for subarray
    // arr[0..i]
    int dp[n];

    // If there is single value, we get the
    // minimum sum equal to arr[0]
    if (n==1)
        return arr[0];

    // If there are two values, we get the
    // minimum sum equal to the minimum of
    // two values
    if (n==2)
        return min(arr[0], arr[1]);

    // If there are three values, return
    // minimum of the three elements of
    // array
    if (n==3)
        return min(arr[0], min(arr[1], arr[2]));

    // If there are four values, return minimum
    // of the four elements of array
    if (n==4)
        return min(min(arr[0], arr[1]),
                   min(arr[2], arr[3]));

    dp[0] = arr[0];
    dp[1] = arr[1];
    dp[2] = arr[2];
    dp[3] = arr[3];

    for (int i=4; i<n; i++)
        dp[i] = arr[i] +
                   min(min(dp[i-1], dp[i-2]),
                       min(dp[i-3], dp[i-4]));

    // Return the minimum of last 4 index
    return min(min(dp[n-1], dp[n-2]),
               min(dp[n-4], dp[n-3]));
}

// Driver code
int main()
{
    int arr[] = {1, 2, 3, 3, 4, 5, 6, 1};
    int n = sizeof(arr)/sizeof(arr[0]);
    cout << minSum(arr, n);
    return 0;
}

Output:

4

This article is contributed by Roshni Agarwal. 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.