最大可能的平衡二进制子串拆分,成本为 K
给定一个二进制数组arr[]和一个值数组val[] 。任务是找到二进制数组的最大可能拆分,使得每个段包含相同数量的0和1 ,最多使用k个硬币。每个拆分成本(val[i] – val[j]) 2 ,其中i和j是拆分段的相邻索引。
例子:
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
方法:可以使用动态规划(自顶向下方法)解决任务。
请按照以下步骤操作:
- 初始化一个二维矩阵,比如dp ,维度为 K * N。
- 对于每个索引,只要 0 和 1 的数量相等,就有两种选择,是否在该索引处进行切割或不在该索引处进行切割。
- 记住值,以便再次使用
- 最大化count_splits的值,以获得由此产生的最大削减。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
int dp[1001][1001];
// Function to find maximum possible splits
// in atmost k coins such that each
// segment contains equal number of 0 and 1
int maximumSplits(int arr[], int val[],
int k, int N)
{
// Base Case
if (k < 0) {
return INT_MIN;
}
// If already have a stored value
// return it
if (dp[k][N] != -1) {
return dp[k][N];
}
// Count for zeros and ones
int zero = 0, one = 0;
// Count for number of splits
int count_split = 0;
int i;
// Iterate over the array and
// search for zeros and ones
for (i = N - 1; i > 0; i--) {
arr[i] == 0 ? zero++ : one++;
// If count of zeros is equal to
// count of ones
if (zero == one) {
// Store the maximum possible one
count_split = max(
count_split,
1
+ maximumSplits(
arr, val,
k - pow(val[i]
- val[i - 1],
2),
i));
}
}
// If index is at 0, find if
// it is zero or one and
// increment the count
if (i == 0) {
arr[0] == 0 ? zero++ : one++;
// If count of zero is not equal to
// count of one, re-initialize
// count_split with 0
if (zero != one) {
count_split = 0;
}
}
// Store the returned value in dp[]
return dp[k][N] = count_split;
}
// Driver Code
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
// Java program for the above approach
public class GFG
{
static int[][] dp = new int[1001][1001];
// Function to find maximum possible splits
// in atmost k coins such that each
// segment contains equal number of 0 and 1
static int maximumSplits(int[] arr, int[] val,
int k, int N)
{
// Base Case
if (k < 0) {
return Integer.MIN_VALUE;
}
// If already have a stored value
// return it
if (dp[k][N] != -1) {
return dp[k][N];
}
// Count for zeros and ones
int zero = 0, one = 0;
// Count for number of splits
int count_split = 0;
int i;
// Iterate over the array and
// search for zeros and ones
for (i = N - 1; i > 0; i--) {
if(arr[i] == 0)
zero++;
else
one++;
// If count of zeros is equal to
// count of ones
if (zero == one) {
// Store the maximum possible one
count_split = Math.max(
count_split,
1
+ maximumSplits(
arr, val,
k - (int)Math.pow(val[i]
- val[i - 1],
2),
i));
}
}
// If index is at 0, find if
// it is zero or one and
// increment the count
if (i == 0) {
if(arr[0] == 0)
zero++;
else
one++;
// If count of zero is not equal to
// count of one, re-initialize
// count_split with 0
if (zero != one) {
count_split = 0;
}
}
// Store the returned value in dp[]
return dp[k][N] = count_split;
}
// Driver code
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));
}
}
// This code is contributed by AnkThon
Python3
# Python Program to implement
# the above approach
dp = [0] * 1001
for i in range(len(dp)):
dp[i] = [-1] * 1001
# Function to find maximum possible splits
# in atmost k coins such that each
# segment contains equal number of 0 and 1
def maximumSplits(arr, val, k, N):
# Base Case
if (k < 0):
return 10 ** (-9)
# If already have a stored value
# return it
if (dp[k][N] != -1) :
return dp[k][N]
# Count for zeros and ones
zero = 0
one = 0
# Count for number of splits
count_split = 0
# Iterate over the array and
# search for zeros and ones
for i in range(N - 1, 0, -1):
if (arr[i] == 0):
zero += 1
else: one += 1
# If count of zeros is equal to
# count of ones
if (zero == one):
# Store the maximum possible one
count_split = max(
count_split, 1
+ maximumSplits(
arr, val,
k - pow(val[i]
- val[i - 1],
2), i))
# If index is at 0, find if
# it is zero or one and
# increment the count
if (i == 0):
if (arr[i] == 0):
zero += 1
else: one -= 1
# If count of zero is not equal to
# count of one, re-initialize
# count_split with 0
if (zero != one):
count_split = 0
# Store the returned value in dp[]
dp[k][N] = count_split
return dp[k][N]
# Driver Code
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))
# This code is contributed by Saurabh Jaiswal
C#
// C# program for the above approach
using System;
public class GFG
{
static int[,] dp = new int[1001, 1001];
// Function to find maximum possible splits
// in atmost k coins such that each
// segment contains equal number of 0 and 1
static int maximumSplits(int[] arr, int[] val,
int k, int N)
{
// Base Case
if (k < 0) {
return Int32.MinValue;
}
// If already have a stored value
// return it
if (dp[k, N] != -1) {
return dp[k, N];
}
// Count for zeros and ones
int zero = 0, one = 0;
// Count for number of splits
int count_split = 0;
int i;
// Iterate over the array and
// search for zeros and ones
for (i = N - 1; i > 0; i--) {
if(arr[i] == 0)
zero++;
else
one++;
// If count of zeros is equal to
// count of ones
if (zero == one) {
// Store the maximum possible one
count_split = Math.Max(
count_split,
1
+ maximumSplits(
arr, val,
k - (int)Math.Pow(val[i]
- val[i - 1],
2),
i));
}
}
// If index is at 0, find if
// it is zero or one and
// increment the count
if (i == 0) {
if(arr[0] == 0)
zero++;
else
one++;
// If count of zero is not equal to
// count of one, re-initialize
// count_split with 0
if (zero != one) {
count_split = 0;
}
}
// Store the returned value in dp[]
return dp[k, N] = count_split;
}
// Driver code
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));
}
}
// This code is contributed by sanjoy_62.
Javascript
输出
2
时间复杂度: O(N*K)
辅助空间:O(N*K)