Open In App

Least cost required to empty an Array by removing elements from front

Improve
Improve
Like Article
Like
Save
Share
Report

Given binary array A[] of size N, the task is to find the minimum cost to remove all elements of the array by performing moves (where the cost of the odd move will be the sum of the elements removed and the cost for the even move will be 0). For more clarification:

  • First Move: This is an odd move, Remove either 1 or 2 elements from the front of the array and the cost of removing will be equal to the sum of those removed elements.
  • Second Move: This is an even move, Remove either 1 or 2 elements from the front of the array and this operation will be performed with cost zero.
  • Third Move: This is an odd move, Remove 1 or 2 elements from the front of the array and the cost of removing them will be equal to the sum of those elements. 

Examples: 

 Input: A[] = {1, 0, 1, 1, 0, 1, 1, 1}
Output: 2
Explanation: Following is the optimal way to perform the above operations: 

  • In first move remove 2 elements that is {1, 0} it will cost 1.
  • In the second move remove 2 elements that are {1, 1} it will cost 0.
  • In third move remove 2 elements that is {0, 1} it will cost 1.
  • In fourth move remove 2 elements that is {1, 1} it will cost 0.

The minimum possible cost to remove all elements is 2.

Input: A[] = {1, 1, 1, 1, 1, 1}
Output: 2
Explanation:  Following is the optimal way to perform the above operations:

  • In the first move remove 1 element that is {1} it will cost 1.
  • In second move remove 2 elements that is {1, 1} it will cost 0.
  • In the third move remove 1 element that is {1} it will cost 1.
  • In fourth move remove 2 elements that is {1, 1} it will cost 0.

The minimum possible cost to remove all elements is 2.

Naive approach: The basic way to solve the problem is as follows:

The basic way to solve this problem is to explore all possible combinations by using a recursive approach.

Time Complexity: O(2N)
Auxiliary Space: O(1)

Efficient Approach:  The above approach can be optimized based on the following idea:

Dynamic programming can be used to solve to this problem.

  • dp[i] represents minimum cost till index i
  • recurrence relation :                                                                                                                                                                                                                  
    •  dp[i] = min(dp[i + 1] + A[i], dp[i + 2] + A[i] + A[i + 1]) when move is odd                                                                                      
    • dp[i] = min(dp[i + 1], dp[i + 2]) when move is even

It can be observed that the recursive function is called exponential times. That means that some states are called repeatedly. So the idea is to store the value of each state. This can be done using by store the value of a state and whenever the function is called, return the stored value without computing again.

Follow the steps below to solve the problem:

  • Create a recursive function that takes two parameters i representing i’th index of array j representing parity of move either even or odd.
  • Call recursive function for both choosing one index and choosing two indexes.
  • Check the base case that the array is empty or not and return 0.
  • Create a 2d array of dp[N][2] initially filled with -1.
  • If the answer for a particular state is computed then save it in dp[i][j].
  • If the answer for a particular state is already computed then just return dp[i][j].

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// dp table initialized with - 1
int dp[100001][2];
 
// Recursive function to calculate minimum
// cost to empty the array
int recur(int i, int j, int A[], int N)
{
 
    // Base case
    if (i == N) {
        return 0;
    }
 
    // If answer for current state is
    // already calculated then just
    // return dp[i][j]
    if (dp[i][j] != -1)
        return dp[i][j];
 
    int ans = INT_MAX;
 
    // Calling recursive function to
    // remove one element for the odd
    // move costing A[i]
    if (j == 0)
        ans = min(ans, recur(i + 1, j ^ 1, A, N) + A[i]);
 
    // Calling recursive function to
    // remove two element for the odd
    // move costing A[i] + A[i + 1]
    if (j == 0 and i + 1 < N)
        ans = min(ans, recur(i + 2, j ^ 1, A, N) + A[i]
                           + A[i + 1]);
 
    // Calling recursive function to
    // remove one element for the even
    // move costing nothing
    if (j == 1)
        ans = min(ans, recur(i + 1, j ^ 1, A, N));
 
    // Calling recursive function to
    // remove two element for the even
    // move costing nothing
    if (j == 1 and i + 1 < N)
        ans = min(ans, recur(i + 2, j ^ 1, A, N));
 
    // Save and return dp value
    return dp[i][j] = ans;
}
 
// Function to calculate minimum cost
// to erase all the elements of array
void minCost(int A[], int N)
{
 
    // Filling dp table with -1
    memset(dp, -1, sizeof(dp));
 
    cout << recur(0, 0, A, N) << endl;
}
 
// Driver Code
int main()
{
 
    // Input 1
    int A[] = { 1, 0, 1, 1, 0, 1, 1, 1 };
    int N = sizeof(A) / sizeof(A[0]);
 
    // Function Call
    minCost(A, N);
 
    // Input 2
    int A1[] = { 1, 1, 1, 1, 1, 1 };
    int N1 = sizeof(A1) / sizeof(A1[0]);
 
    // Function Call
    minCost(A1, N1);
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
 
class GFG {
    // dp table initialized with - 1
    static int dp[][]=new int[100001][2];
 
    // Recursive function to calculate minimum
    // cost to empty the array
    public static int recur(int i, int j, int A[], int N)
    {
 
        // Base case
        if (i == N) {
            return 0;
        }
 
        // If answer for current state is
        // already calculated then just
        // return dp[i][j]
        if (dp[i][j] != -1)
            return dp[i][j];
 
        int ans = Integer.MAX_VALUE;
 
        // Calling recursive function to
        // remove one element for the odd
        // move costing A[i]
        if (j == 0)
            ans = Math.min(ans, recur(i + 1, j ^ 1, A, N)
                                    + A[i]);
 
        // Calling recursive function to
        // remove two element for the odd
        // move costing A[i] + A[i + 1]
        if (j == 0 && i + 1 < N)
            ans = Math.min(ans, recur(i + 2, j ^ 1, A, N)
                                    + A[i] + A[i + 1]);
 
        // Calling recursive function to
        // remove one element for the even
        // move costing nothing
        if (j == 1)
            ans = Math.min(ans, recur(i + 1, j ^ 1, A, N));
 
        // Calling recursive function to
        // remove two element for the even
        // move costing nothing
        if (j == 1 && i + 1 < N)
            ans = Math.min(ans, recur(i + 2, j ^ 1, A, N));
 
        // Save and return dp value
        return dp[i][j] = ans;
    }
 
    // Function to calculate minimum cost
    // to erase all the elements of array
    public static void minCost(int A[], int N)
    {
 
        // Filling dp table with -1
        for (int i = 0; i < 100001; i++) {
            for (int j = 0; j < 2; j++) {
                dp[i][j] = -1;
            }
        }
 
        System.out.println(recur(0, 0, A, N));
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Input 1
        int A[] = { 1, 0, 1, 1, 0, 1, 1, 1 };
        int N = A.length;
 
        // Function Call
        minCost(A, N);
 
        // Input 2
        int A1[] = { 1, 1, 1, 1, 1, 1 };
        int N1 = A1.length;
 
        // Function Call
        minCost(A1, N1);
    }
}
 
// This code is contributed by Rohit Pradhan


Python3




# Python3 program to implement the approach
 
# dp table initialized with - 1
dp = [[-1 for i in range(2)] for j in range(100001)]
 
# Recursive function to calculate minimum
# cost to empty the array
def recur(i: int, j: int, A: list, N: int) -> int:
    """
    i: int: current index
    j: int: 0 for odd move and 1 for even move
    A: list: array
    N: int: size of array
    """
    # Base case
    if i == N:
        return 0
 
    # If answer for current state is
    # already calculated then just
    # return dp[i][j]
    if dp[i][j] != -1:
        return dp[i][j]
 
    ans = float("inf")
 
    # Calling recursive function to
    # remove one element for the odd
    # move costing A[i]
    if j == 0:
        ans = min(ans, recur(i + 1, j ^ 1, A, N) + A[i])
 
    # Calling recursive function to
    # remove two element for the odd
    # move costing A[i] + A[i + 1]
    if j == 0 and i + 1 < N:
        ans = min(ans, recur(i + 2, j ^ 1, A, N) + A[i] + A[i + 1])
 
    # Calling recursive function to
    # remove one element for the even
    # move costing nothing
    if j == 1:
        ans = min(ans, recur(i + 1, j ^ 1, A, N))
 
    # Calling recursive function to
    # remove two element for the even
    # move costing nothing
    if j == 1 and i + 1 < N:
        ans = min(ans, recur(i + 2, j ^ 1, A, N))
 
    # Save and return dp value
    dp[i][j] = ans
    return ans
 
# Function to calculate minimum cost
# to erase all the elements of array
def minCost(A: list, N: int):
    """
    A: list: array
    N: int: size of array
    """
    print(recur(0, 0, A, N))
 
# Driver Code
if __name__ == "__main__":
    # Input 1
    A = [1, 0, 1, 1, 0, 1, 1, 1]
    N = len(A)
 
    # Function Call
    minCost(A, N)
 
    # Input 2
    A1 = [1, 1, 1, 1, 1, 1]
    N1 = len(A1)
 
    # Function Call
    minCost(A1, N1)
 
    # This code is contributed by lokeshpotta20.


C#




// C# code implementation
 
using System;
 
public class GFG {
 
    // dp table initialized with - 1
    static int[, ] dp = new int[100001, 2];
 
    // Recursive function to calculate minimum cost to empty
    // the array
    static int recur(int i, int j, int[] A, int N)
    {
 
        // Base case
        if (i == N) {
            return 0;
        }
 
        // If answer for current state is already calculated
        // then just return dp[i,j]
        if (dp[i, j] != -1)
            return dp[i, j];
 
        int ans = int.MaxValue;
 
        // Calling recursive function to remove one element
        // for the odd move costing A[i]
        if (j == 0)
            ans = Math.Min(ans, recur(i + 1, j ^ 1, A, N)
                                    + A[i]);
 
        // Calling recursive function to remove two element
        // for the odd move costing A[i] + A[i + 1]
        if (j == 0 && i + 1 < N)
            ans = Math.Min(ans, recur(i + 2, j ^ 1, A, N)
                                    + A[i] + A[i + 1]);
 
        // Calling recursive function to remove one element
        // for the even move costing nothing
        if (j == 1)
            ans = Math.Min(ans, recur(i + 1, j ^ 1, A, N));
 
        // Calling recursive function to remove two element
        // for the even move costing nothing
        if (j == 1 && i + 1 < N)
            ans = Math.Min(ans, recur(i + 2, j ^ 1, A, N));
 
        // Save and return dp value
        return dp[i, j] = ans;
    }
 
    // Function to calculate minimum cost to erase all the
    // elements of array
    static void minCost(int[] A, int N)
    {
 
        // Filling dp table with -1
        for (int i = 0; i < 100001; i++) {
            for (int j = 0; j < 2; j++) {
                dp[i, j] = -1;
            }
        }
 
        Console.WriteLine(recur(0, 0, A, N));
    }
 
    static public void Main()
    {
 
        // Code
        // Input 1
        int[] A = { 1, 0, 1, 1, 0, 1, 1, 1 };
        int N = A.Length;
 
        // Function Call
        minCost(A, N);
 
        // Input 2
        int[] A1 = { 1, 1, 1, 1, 1, 1 };
        int N1 = A1.Length;
 
        // Function Call
        minCost(A1, N1);
    }
}
 
// This code is contributed by karthik.


Javascript




// JS code to implement the approach
 
// dp table initialized with - 1
let dp = new Array(100001);
for(let i = 0; i < 100001; i++)
    dp[i] = new Array(2);
 
// Recursive function to calculate minimum
// cost to empty the array
function recur( i,  j,  A,  N)
{
 
    // Base case
    if (i == N) {
        return 0;
    }
 
    // If answer for current state is
    // already calculated then just
    // return dp[i][j]
    if (dp[i][j] != -1)
        return dp[i][j];
 
    let ans = Number.MAX_SAFE_INTEGER;
 
    // Calling recursive function to
    // remove one element for the odd
    // move costing A[i]
    if (j == 0)
        ans = Math.min(ans, recur(i + 1, j ^ 1, A, N) + A[i]);
 
    // Calling recursive function to
    // remove two element for the odd
    // move costing A[i] + A[i + 1]
    if (j == 0 && i + 1 < N)
        ans = Math.min(ans, recur(i + 2, j ^ 1, A, N) + A[i]
                           + A[i + 1]);
 
    // Calling recursive function to
    // remove one element for the even
    // move costing nothing
    if (j == 1)
        ans = Math.min(ans, recur(i + 1, j ^ 1, A, N));
 
    // Calling recursive function to
    // remove two element for the even
    // move costing nothing
    if (j == 1 && i + 1 < N)
        ans = Math.min(ans, recur(i + 2, j ^ 1, A, N));
 
    // Save and return dp value
    return dp[i][j] = ans;
}
 
// Function to calculate minimum cost
// to erase all the elements of array
function minCost( A,  N)
{
 
    // Filling dp table with -1
    for(let i=0; i<100001; i++)
        for(let j=0; j<2; j++)
            dp[i][j]=-1;
 
    console.log(recur(0, 0, A, N)+"<br>");
}
 
// Driver Code
// Input 1
let A = [ 1, 0, 1, 1, 0, 1, 1, 1 ];
let N = A.length;
 
// Function Call
minCost(A, N);
 
// Input 2
let A1 = [ 1, 1, 1, 1, 1, 1 ];
let N1 = A1.length;
 
// Function Call
minCost(A1, N1);


Output

2
2

Complexity analysis:

The time complexity of the given recursive function is exponential, specifically O(2^N), where N is the size of the input array. This is because for each element in the array, we have two choices – either remove one element or remove two elements. Therefore, the number of recursive calls made is proportional to the number of possible ways we can remove elements from the array, which is 2 raised to the power of N.

The space complexity of the given function is O(N), as we are using a 2D array of size (N+1)x2 to store the intermediate results of the recursive calls. This is because for each element in the array, we need to store the minimum cost of emptying the array when starting from that element and making either an odd or even move. Therefore, the total number of entries in the 2D array is (N+1)x2

Related Articles:



Last Updated : 28 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads