Maximum possible balanced binary substring splits with at most cost K
Given a binary array arr[] and a value array val[]. The task is to find the maximum possible splits of the binary array that can be done such that each segment contains an equal number of 0s and 1s using at most k coins. Each split costs (val[i] – val[j])2, where i and j are the adjacent indices of the split segment.
Examples:
Input: arr[] = {0, 1, 0, 0, 1, 1}, val[] = {2, 5, 1, 3, 6, 10}, k = 20
Output: 1
Explanation: Splits can be done in the following way: 0 1 | 0 0 1 1 and cost = (5 – 1)2 = 16 ≤ 20.
Input: arr[] = {1, 0, 0, 1, 0, 1, 1, 0}, val[] = {9, 7, 5, 2, 4, 12, 3, 1], k = 10
Output: 2
Explanation: Splits can be done in the following way: 1 0 | 0 1 | 0 1 1 0
Approach: The task can be solved using dynamic programming (Top-down approach).
Follow the below steps:
- Initialize a 2d matrix say dp of dimensions K * N.
- For every index, there are two choices, whether to make a cut at that index or to not make a cut at that index, provided that the number of zeroes and ones are equal.
- Memoize the values, to be used again
- Maximize the value of count_splits, to get the resultant maximum cuts.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[1001][1001];
int maximumSplits( int arr[], int val[],
int k, int N)
{
if (k < 0) {
return INT_MIN;
}
if (dp[k][N] != -1) {
return dp[k][N];
}
int zero = 0, one = 0;
int count_split = 0;
int i;
for (i = N - 1; i > 0; i--) {
arr[i] == 0 ? zero++ : one++;
if (zero == one) {
count_split = max(
count_split,
1
+ maximumSplits(
arr, val,
k - pow (val[i]
- val[i - 1],
2),
i));
}
}
if (i == 0) {
arr[0] == 0 ? zero++ : one++;
if (zero != one) {
count_split = 0;
}
}
return dp[k][N] = count_split;
}
int main()
{
int arr[] = { 1, 0, 0, 1, 0, 1, 1, 0 };
int val[] = { 9, 7, 5, 2, 4, 12, 3, 1 };
int k = 10;
int N = sizeof (arr) / sizeof (arr[0]);
memset (dp, -1, sizeof (dp));
cout << maximumSplits(arr, val, k, N);
return 0;
}
|
Java
public class GFG
{
static int [][] dp = new int [ 1001 ][ 1001 ];
static int maximumSplits( int [] arr, int [] val,
int k, int N)
{
if (k < 0 ) {
return Integer.MIN_VALUE;
}
if (dp[k][N] != - 1 ) {
return dp[k][N];
}
int zero = 0 , one = 0 ;
int count_split = 0 ;
int i;
for (i = N - 1 ; i > 0 ; i--) {
if (arr[i] == 0 )
zero++;
else
one++;
if (zero == one) {
count_split = Math.max(
count_split,
1
+ maximumSplits(
arr, val,
k - ( int )Math.pow(val[i]
- val[i - 1 ],
2 ),
i));
}
}
if (i == 0 ) {
if (arr[ 0 ] == 0 )
zero++;
else
one++;
if (zero != one) {
count_split = 0 ;
}
}
return dp[k][N] = count_split;
}
public static void main(String[] args)
{
int [] arr = { 1 , 0 , 0 , 1 , 0 , 1 , 1 , 0 };
int [] val = { 9 , 7 , 5 , 2 , 4 , 12 , 3 , 1 };
int k = 10 ;
int N = arr.length;
int i, j;
for (i= 0 ;i< 1001 ;i++)
{
for (j= 0 ;j< 1001 ;j++)
{
dp[i][j] = - 1 ;
}
}
System.out.println(maximumSplits(arr, val, k, N));
}
}
|
Python3
dp = [ 0 ] * 1001
for i in range ( len (dp)):
dp[i] = [ - 1 ] * 1001
def maximumSplits(arr, val, k, N):
if (k < 0 ):
return 10 * * ( - 9 )
if (dp[k][N] ! = - 1 ) :
return dp[k][N]
zero = 0
one = 0
count_split = 0
for i in range (N - 1 , 0 , - 1 ):
if (arr[i] = = 0 ):
zero + = 1
else : one + = 1
if (zero = = one):
count_split = max (
count_split, 1
+ maximumSplits(
arr, val,
k - pow (val[i]
- val[i - 1 ],
2 ), i))
if (i = = 0 ):
if (arr[i] = = 0 ):
zero + = 1
else : one - = 1
if (zero ! = one):
count_split = 0
dp[k][N] = count_split
return dp[k][N]
arr = [ 1 , 0 , 0 , 1 , 0 , 1 , 1 , 0 ]
val = [ 9 , 7 , 5 , 2 , 4 , 12 , 3 , 1 ]
k = 10
N = len (arr)
print (maximumSplits(arr, val, k, N))
|
C#
using System;
public class GFG
{
static int [,] dp = new int [1001, 1001];
static int maximumSplits( int [] arr, int [] val,
int k, int N)
{
if (k < 0) {
return Int32.MinValue;
}
if (dp[k, N] != -1) {
return dp[k, N];
}
int zero = 0, one = 0;
int count_split = 0;
int i;
for (i = N - 1; i > 0; i--) {
if (arr[i] == 0)
zero++;
else
one++;
if (zero == one) {
count_split = Math.Max(
count_split,
1
+ maximumSplits(
arr, val,
k - ( int )Math.Pow(val[i]
- val[i - 1],
2),
i));
}
}
if (i == 0) {
if (arr[0] == 0)
zero++;
else
one++;
if (zero != one) {
count_split = 0;
}
}
return dp[k, N] = count_split;
}
public static void Main(String[] args)
{
int [] arr = { 1, 0, 0, 1, 0, 1, 1, 0 };
int [] val = { 9, 7, 5, 2, 4, 12, 3, 1 };
int k = 10;
int N = arr.Length;
int i, j;
for (i=0;i<1001;i++)
{
for (j=0;j<1001;j++)
{
dp[i, j] = -1;
}
}
Console.WriteLine(maximumSplits(arr, val, k, N));
}
}
|
Javascript
<script>
let dp = new Array(1001);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(1001).fill(-1);
}
function maximumSplits(arr, val,
k, N)
{
if (k < 0) {
return Number.MIN_VALUE;
}
if (dp[k][N] != -1) {
return dp[k][N];
}
let zero = 0, one = 0;
let count_split = 0;
let i;
for (i = N - 1; i > 0; i--) {
arr[i] == 0 ? zero++ : one++;
if (zero == one)
{
count_split = Math.max(
count_split, 1
+ maximumSplits(
arr, val,
k - Math.pow(val[i]
- val[i - 1],
2), i));
}
}
if (i == 0) {
arr[0] == 0 ? zero++ : one++;
if (zero != one) {
count_split = 0;
}
}
return dp[k][N] = count_split;
}
let arr = [1, 0, 0, 1, 0, 1, 1, 0];
let val = [9, 7, 5, 2, 4, 12, 3, 1];
let k = 10;
let N = arr.length;
document.write(maximumSplits(arr, val, k, N))
</script>
|
Time Complexity: O(N*K)
Auxiliary Space: O(N*K)
Last Updated :
24 Nov, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...