给定一个二进制字符串S ,由 0 和 1 组成。您必须以满足以下条件的方式将 0 和 1 容纳到K 个存储桶中:
- 您将 0 和 1 填充到存储桶中,并保留0 和 1 的相对顺序。例如,您不能将 S[1] 放入第 2 桶,将 S[0] 放入第 1 桶。您必须保留二进制字符串的原始顺序。
- 任何桶都不应留空,字符串的任何元素都不应留空。
- 每个桶的(0 的数量 * 1 的数量)的所有乘积之和应该是所有可能的住宿安排中的最小值。
如果无法解决,则打印-1。
例子:
Input: S = "0001", K = 2
Output: 0
We have 3 choices {"0", "001"}, {"00", "01"}, {"000", 1}
First choice, we will get 1*0 + 2*1 = 2
Second choice, we will get 2*0 + 1*1 = 1
Third choice, we will get 3*0 + 0*1 = 0
Out of all the 3 choices, the third choice
is giving the minimum answer.
Input: S = "0101", K = 1
Output: 1
递归实现:你必须在不干扰上述条件的情况下将二进制字符串容纳到 K 个桶中。然后可以通过首先填充第 i 个存储桶(从 0 开始)通过将元素从start 到 N (N = 二进制字符串的长度)并继续添加计数 0 和 1 直到开始索引来制作简单的递归解决方案。对于每次迭代,如果在开始之前有x 个零和 y 个 1 ,那么f(start, K) = x * y + f(start + 1, K – 1)会重复发生,因为下一次调整将从 (start + 1)-第一个索引和剩余的桶将 K – 1。
所以,递归公式将是——
F(start, current_bucket) = | |
| min | F(i + 1, next_bucket) + (ones * zeroes in current_bucket)
| |
| i = start to N
自上而下的动态方法:
通过将 start 和 bucket 变量的不同组合的结果保存到二维 DP 数组中,可以将递归关系更改为动态解决方案。我们可以使用应该保留字符串顺序的事实。您可以使用二维数组保存大小[size of 字符串 * buckets] 的状态,其中 dp[i][j] 将告诉我们使用 j + 1 个桶的字符串的第 i 个索引之前的最小适应值。我们的最终答案将在dp[N-1][K-1] 中。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// 2-D dp array saving different states
// dp[i][j] = minimum value of accommodation
// till i'th index of the string
// using j+1 number of buckets.
vector > dp;
// Function to find the minimum required
// sum using dynamic programming
int solveUtil(int start, int bucket, string str, int K)
{
int N = str.size();
// If both start and bucket reached end then
// return 0 else that arrangement is not possible
// so return INT_MAX
if (start == N) {
if (bucket == K)
return 0;
return INT_MAX;
}
// Corner case
if (bucket == K)
return INT_MAX;
// If state if already calculated
// then return its answer
if (dp[start][bucket] != -1)
return dp[start][bucket];
int zeroes = 0;
int ones = 0;
int ans = INT_MAX;
// Start filling zeroes and ones which to be accommodated
// in jth bucket then ans for current arrangement will be
// ones*zeroes + recur(i+1, bucket+1)
for (int i = start; i < N; ++i) {
if (str[i] == '1')
ones++;
else
zeroes++;
if (ones * zeroes > ans)
break;
int temp = solveUtil(i + 1, bucket + 1, str, K);
// If this arrangement is not possible then
// don't calculate further
if (temp != INT_MAX) {
ans = min(ans, temp + (ones * zeroes));
}
}
return dp[start][bucket] = ans;
}
// Function to initialize the dp and call
// solveUtil() method to get the answer
int solve(string str, int K)
{
int N = str.size();
dp.clear();
dp.resize(N, vector(K, -1));
// Start with 0-th index and 1 bucket
int ans = solveUtil(0, 0, str, K);
return ans == INT_MAX ? -1 : ans;
}
// Driver code
int main()
{
string S = "0101";
// K buckets
int K = 2;
cout << solve(S, K) << endl;
return 0;
}
Java
// Java implementation of the approach
import java.io.*;
import java.util.*;
class GFG{
// 2-D dp array saving different states
// dp[i][j] = minimum value of accommodation
// till i'th index of the string
// using j+1 number of buckets.
static int[][] dp;
// Function to find the minimum required
// sum using dynamic programming
static int solveUtil(int start, int bucket,
String str, int K)
{
int N = str.length();
// If both start and bucket reached end
// then return 0 else that arrangement
// is not possible so return INT_MAX
if (start == N)
{
if (bucket == K)
{
return 0;
}
return Integer.MAX_VALUE;
}
// Corner case
if (bucket == K)
{
return Integer.MAX_VALUE;
}
// If state if already calculated
// then return its answer
if (dp[start][bucket] != -1)
{
return dp[start][bucket];
}
int zeroes = 0;
int ones = 0;
int ans = Integer.MAX_VALUE;
// Start filling zeroes and ones which to be
// accommodated in jth bucket then ans for
// current arrangement will be
// ones*zeroes + recur(i+1, bucket+1)
for(int i = start; i < N; ++i)
{
if (str.charAt(i) == '1')
{
ones++;
}
else
{
zeroes++;
}
if (ones * zeroes > ans)
{
break;
}
int temp = solveUtil(i + 1, bucket + 1, str, K);
// If this arrangement is not possible then
// don't calculate further
if (temp != Integer.MAX_VALUE)
{
ans = Math.min(ans, temp + (ones * zeroes));
}
}
return dp[start][bucket] = ans;
}
// Function to initialize the dp and call
// solveUtil() method to get the answer
static int solve(String str, int K)
{
int N = str.length();
dp = new int[N][K];
for(int[] row : dp)
{
Arrays.fill(row, -1);
}
// Start with 0-th index and 1 bucket
int ans = solveUtil(0, 0, str, K);
return ans == Integer.MAX_VALUE ? -1 : ans;
}
// Driver code
public static void main(String[] args)
{
String S = "0101";
// K buckets
int K = 2;
System.out.println(solve(S, K));
}
}
// This code is contributed by rag2127
Python3
# Python3 implementation of the approach
# 2-D dp array saving different states
# dp[i][j] = minimum value of accommodation
# till i'th index of the str1ing
# using j+1 number of buckets.
# Function to find the minimum required
# sum using dynamic programming
def solveUtil(start, bucket, str1, K,dp):
N = len(str1)
# If both start and bucket reached end then
# return 0 else that arrangement is not possible
# so return INT_MAX
if (start == N) :
if (bucket == K):
return 0
return 10**9
# Corner case
if (bucket == K):
return 10**9
# If state if already calculated
# then return its answer
if (dp[start][bucket] != -1):
return dp[start][bucket]
zeroes = 0
ones = 0
ans = 10**9
# Start filling zeroes and ones which to be accommodated
# in jth bucket then ans for current arrangement will be
# ones*zeroes + recur(i+1, bucket+1)
for i in range(start,N):
if (str1[i] == '1'):
ones += 1
else:
zeroes += 1
if (ones * zeroes > ans):
break
temp = solveUtil(i + 1, bucket + 1, str1, K,dp)
# If this arrangement is not possible then
# don't calculate further
if (temp != 10**9):
ans = min(ans, temp + (ones * zeroes))
dp[start][bucket] = ans
return ans
# Function to initialize the dp and call
# solveUtil() method to get the answer
def solve(str1, K):
N = len(str1)
dp = [[-1 for i in range(K)] for i in range(N)]
# Start with 0-th index and 1 bucket
ans = solveUtil(0, 0, str1, K,dp)
if ans == 10**9:
return -1
else:
return ans
# Driver code
s = "0101"
S=[i for i in s]
# K buckets
K = 2
print(solve(S, K))
# This code is contributed by mohit kumar 29
C#
// C# implementation of the approach
using System;
class GFG
{
// 2-D dp array saving different states
// dp[i][j] = minimum value of accommodation
// till i'th index of the string
// using j+1 number of buckets.
static int[,] dp;
// Function to find the minimum required
// sum using dynamic programming
static int solveUtil(int start, int bucket,
string str, int K)
{
int N = str.Length;
// If both start and bucket reached end
// then return 0 else that arrangement
// is not possible so return INT_MAX
if (start == N)
{
if (bucket == K)
{
return 0;
}
return Int32.MaxValue;
}
// Corner case
if (bucket == K)
{
return Int32.MaxValue;
}
// If state if already calculated
// then return its answer
if (dp[start,bucket] != -1)
{
return dp[start, bucket];
}
int zeroes = 0;
int ones = 0;
int ans = Int32.MaxValue;
// Start filling zeroes and ones which to be
// accommodated in jth bucket then ans for
// current arrangement will be
// ones*zeroes + recur(i+1, bucket+1)
for(int i = start; i < N; ++i)
{
if (str[i] == '1')
{
ones++;
}
else
{
zeroes++;
}
if (ones * zeroes > ans)
{
break;
}
int temp = solveUtil(i + 1, bucket + 1, str, K);
// If this arrangement is not possible then
// don't calculate further
if (temp != Int32.MaxValue)
{
ans = Math.Min(ans, temp + (ones * zeroes));
}
}
return dp[start, bucket] = ans;
}
// Function to initialize the dp and call
// solveUtil() method to get the answer
static int solve(string str, int K)
{
int N = str.Length;
dp = new int[N, K];
for(int i = 0; i < N; i++)
{
for(int j = 0; j < K; j++)
{
dp[i, j] = -1;
}
}
// Start with 0-th index and 1 bucket
int ans = solveUtil(0, 0, str, K);
return ans == Int32.MaxValue ? -1 : ans;
}
// Driver code
static void Main()
{
string S = "0101";
// K buckets
int K = 2;
Console.WriteLine(solve(S, K));
}
}
// This code is contributed by divyeshrabadiya07.
Javascript
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to find the minimum required
// sum using dynamic programming
int solve(string str, int K)
{
int n = str.length();
// dp[i][j] = minimum val of accommodation
// till j'th index of the string
// using i+1 number of buckets.
// Final ans will be in dp[n-1][K-1]
long long dp[K][n];
// Initialise dp with all states as 0
memset(dp, 0, sizeof dp);
// Corner cases
if (n < K)
return -1;
else if (n == K)
return 0;
// Filling first row, if only 1 bucket then simple count
// number of zeros and ones and do the multiplication
long long zeroes = 0, ones = 0;
for (int i = 0; i < n; i++) {
if (str[i] == '0')
zeroes++;
else
ones++;
dp[0][i] = ones * zeroes;
}
for (int s = 1; s < K; s++) {
for (int i = 0; i < n; i++) {
dp[s][i] = INT_MAX;
ones = 0;
zeroes = 0;
for (int k = i; k >= 0; k--) {
if (str[k] == '0')
zeroes++;
else
ones++;
// If k = 0 then this arrangement is not possible
dp[s][i] = min(dp[s][i],
+((k - 1 >= 0)
? ones * zeroes + dp[s - 1][k - 1]
: INT_MAX));
}
}
}
// If no arrangement is possible then
// our answer will remain INT_MAX so return -1
return (dp[K - 1][n - 1] == INT_MAX) ? -1 : dp[K - 1][n - 1];
}
// Driver code
int main()
{
string S = "0101";
// K buckets
int K = 2;
cout << solve(S, K) << endl;
return 0;
}
Java
// Java implementation of the approach
class GFG
{
// Function to find the minimum required
// sum using dynamic programming
static long solve(String str, int K)
{
int n = str.length();
// dp[i][j] = minimum val of accommodation
// till j'th index of the string
// using i+1 number of buckets.
// Final ans will be in dp[n-1][K-1]
long dp[][] = new long[K][n];
// Corner cases
if (n < K)
return -1;
else if (n == K)
return 0;
// Filling first row, if only 1 bucket then simple count
// number of zeros and ones and do the multiplication
long zeroes = 0, ones = 0;
for (int i = 0; i < n; i++)
{
if (str.charAt(i) == '0')
zeroes++;
else
ones++;
dp[0][i] = ones * zeroes;
}
for (int s = 1; s < K; s++)
{
for (int i = 0; i < n; i++)
{
dp[s][i] = Integer.MAX_VALUE;
ones = 0;
zeroes = 0;
for (int k = i; k >= 0; k--)
{
if (str.charAt(k) == '0')
zeroes++;
else
ones++;
// If k = 0 then this arrangement is not possible
dp[s][i] = Math.min(dp[s][i],
+((k - 1 >= 0)
? ones * zeroes + dp[s - 1][k - 1]
: Integer.MAX_VALUE));
}
}
}
// If no arrangement is possible then
// our answer will remain INT_MAX so return -1
return (dp[K - 1][n - 1] == Integer.MAX_VALUE) ? -1 : dp[K - 1][n - 1];
}
// Driver code
public static void main (String[] args)
{
String S = "0101";
// K buckets
int K = 2;
System.out.println(solve(S, K));
}
}
// This code is contributed by ihritik
Python3
# Python3 implementation of the approach
import sys
# Function to find the minimum required
# sum using dynamic programming
def solve(Str, K):
n = len(Str)
# dp[i][j] = minimum val of accommodation
# till j'th index of the string
# using i+1 number of buckets.
# Final ans will be in dp[n-1][K-1]
# Initialise dp with all states as 0
dp = [[0 for i in range(n)] for j in range(K)]
# Corner cases
if(n < K):
return -1
elif(n == K):
return 0
# Filling first row, if only 1 bucket then simple count
# number of zeros and ones and do the multiplication
zeroes = 0
ones = 0
for i in range(n):
if(Str[i] == '0'):
zeroes += 1
else:
ones += 1
dp[0][i] = ones * zeroes
for s in range(1, K):
for i in range(n):
dp[s][i] = sys.maxsize
ones = 0
zeroes = 0
for k in range(i, -1, -1):
if(Str[k] == '0'):
zeroes += 1
else:
ones += 1
# If k = 0 then this arrangement
# is not possible
temp = 0
if(k - 1 >= 0):
temp = ones * zeroes + dp[s - 1][k - 1]
else:
temp = sys.maxsize
dp[s][i] = min(dp[s][i], temp)
# If no arrangement is possible then
# our answer will remain INT_MAX so return -1
if(dp[K - 1][n - 1] == sys.maxsize):
return -1
else:
return dp[K - 1][n - 1]
# Driver code
S = "0101"
# K buckets
K = 2
print(solve(S, K))
# This code is contributed by avanitrachhadiya2155
C#
// C# implementation of the approach
using System;
class GFG
{
// Function to find the minimum required
// sum using dynamic programming
static long solve(string str, int K)
{
int n = str.Length;
// dp[i, j] = minimum val of accommodation
// till j'th index of the string
// using i+1 number of buckets.
// Final ans will be in dp[n-1, K-1]
long [, ] dp = new long[K, n];
// Corner cases
if (n < K)
return -1;
else if (n == K)
return 0;
// Filling first row, if only 1 bucket then simple count
// number of zeros and ones and do the multiplication
long zeroes = 0, ones = 0;
for (int i = 0; i < n; i++)
{
if (str[i] == '0')
zeroes++;
else
ones++;
dp[0, i] = ones * zeroes;
}
for (int s = 1; s < K; s++)
{
for (int i = 0; i < n; i++)
{
dp[s, i] = Int32.MaxValue;
ones = 0;
zeroes = 0;
for (int k = i; k >= 0; k--)
{
if (str[k] == '0')
zeroes++;
else
ones++;
// If k = 0 then this arrangement is not possible
dp[s, i] = Math.Min(dp[s, i],
+((k - 1 >= 0)
? ones * zeroes + dp[s - 1, k - 1]
: Int32.MaxValue));
}
}
}
// If no arrangement is possible then
// our answer will remain INT_MAX so return -1
return (dp[K - 1, n - 1] == Int32.MaxValue) ? -1 : dp[K - 1, n - 1];
}
// Driver code
public static void Main (string[] args)
{
string S = "0101";
// K buckets
int K = 2;
Console.WriteLine(solve(S, K));
}
}
// This code is contributed by ihritik
Javascript
2
时间复杂度: O(N 3 )
空间复杂度: O(N 2 )
此解决方案仍未优化,因为它多次调用相同的状态。所以,现在看看优化的自下而上 DP 方法。
自底向上动态方法:让我们先尝试考虑最终状态。这里的变量是桶的数量和字符串的索引。令dp[i][j] 是字符串元素 0 到 j-1 和 i 个桶的最小乘积总和。现在要定义我们的转换函数,我们必须从后面开始,并考虑在每个可能的位置 k 进行分区。因此我们的转换函数看起来像:
dp [i][j] = for all k = 0 to j min(dp[i][k-1] + numberOfZeroes * numberOfOnes)
for i = 0 (single partition) simple count number of 0's and 1's and do the multiplication.
And if number of buckets is more than string length till now ans is -1 as we cant fill all
the available buckets.
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to find the minimum required
// sum using dynamic programming
int solve(string str, int K)
{
int n = str.length();
// dp[i][j] = minimum val of accommodation
// till j'th index of the string
// using i+1 number of buckets.
// Final ans will be in dp[n-1][K-1]
long long dp[K][n];
// Initialise dp with all states as 0
memset(dp, 0, sizeof dp);
// Corner cases
if (n < K)
return -1;
else if (n == K)
return 0;
// Filling first row, if only 1 bucket then simple count
// number of zeros and ones and do the multiplication
long long zeroes = 0, ones = 0;
for (int i = 0; i < n; i++) {
if (str[i] == '0')
zeroes++;
else
ones++;
dp[0][i] = ones * zeroes;
}
for (int s = 1; s < K; s++) {
for (int i = 0; i < n; i++) {
dp[s][i] = INT_MAX;
ones = 0;
zeroes = 0;
for (int k = i; k >= 0; k--) {
if (str[k] == '0')
zeroes++;
else
ones++;
// If k = 0 then this arrangement is not possible
dp[s][i] = min(dp[s][i],
+((k - 1 >= 0)
? ones * zeroes + dp[s - 1][k - 1]
: INT_MAX));
}
}
}
// If no arrangement is possible then
// our answer will remain INT_MAX so return -1
return (dp[K - 1][n - 1] == INT_MAX) ? -1 : dp[K - 1][n - 1];
}
// Driver code
int main()
{
string S = "0101";
// K buckets
int K = 2;
cout << solve(S, K) << endl;
return 0;
}
Java
// Java implementation of the approach
class GFG
{
// Function to find the minimum required
// sum using dynamic programming
static long solve(String str, int K)
{
int n = str.length();
// dp[i][j] = minimum val of accommodation
// till j'th index of the string
// using i+1 number of buckets.
// Final ans will be in dp[n-1][K-1]
long dp[][] = new long[K][n];
// Corner cases
if (n < K)
return -1;
else if (n == K)
return 0;
// Filling first row, if only 1 bucket then simple count
// number of zeros and ones and do the multiplication
long zeroes = 0, ones = 0;
for (int i = 0; i < n; i++)
{
if (str.charAt(i) == '0')
zeroes++;
else
ones++;
dp[0][i] = ones * zeroes;
}
for (int s = 1; s < K; s++)
{
for (int i = 0; i < n; i++)
{
dp[s][i] = Integer.MAX_VALUE;
ones = 0;
zeroes = 0;
for (int k = i; k >= 0; k--)
{
if (str.charAt(k) == '0')
zeroes++;
else
ones++;
// If k = 0 then this arrangement is not possible
dp[s][i] = Math.min(dp[s][i],
+((k - 1 >= 0)
? ones * zeroes + dp[s - 1][k - 1]
: Integer.MAX_VALUE));
}
}
}
// If no arrangement is possible then
// our answer will remain INT_MAX so return -1
return (dp[K - 1][n - 1] == Integer.MAX_VALUE) ? -1 : dp[K - 1][n - 1];
}
// Driver code
public static void main (String[] args)
{
String S = "0101";
// K buckets
int K = 2;
System.out.println(solve(S, K));
}
}
// This code is contributed by ihritik
蟒蛇3
# Python3 implementation of the approach
import sys
# Function to find the minimum required
# sum using dynamic programming
def solve(Str, K):
n = len(Str)
# dp[i][j] = minimum val of accommodation
# till j'th index of the string
# using i+1 number of buckets.
# Final ans will be in dp[n-1][K-1]
# Initialise dp with all states as 0
dp = [[0 for i in range(n)] for j in range(K)]
# Corner cases
if(n < K):
return -1
elif(n == K):
return 0
# Filling first row, if only 1 bucket then simple count
# number of zeros and ones and do the multiplication
zeroes = 0
ones = 0
for i in range(n):
if(Str[i] == '0'):
zeroes += 1
else:
ones += 1
dp[0][i] = ones * zeroes
for s in range(1, K):
for i in range(n):
dp[s][i] = sys.maxsize
ones = 0
zeroes = 0
for k in range(i, -1, -1):
if(Str[k] == '0'):
zeroes += 1
else:
ones += 1
# If k = 0 then this arrangement
# is not possible
temp = 0
if(k - 1 >= 0):
temp = ones * zeroes + dp[s - 1][k - 1]
else:
temp = sys.maxsize
dp[s][i] = min(dp[s][i], temp)
# If no arrangement is possible then
# our answer will remain INT_MAX so return -1
if(dp[K - 1][n - 1] == sys.maxsize):
return -1
else:
return dp[K - 1][n - 1]
# Driver code
S = "0101"
# K buckets
K = 2
print(solve(S, K))
# This code is contributed by avanitrachhadiya2155
C#
// C# implementation of the approach
using System;
class GFG
{
// Function to find the minimum required
// sum using dynamic programming
static long solve(string str, int K)
{
int n = str.Length;
// dp[i, j] = minimum val of accommodation
// till j'th index of the string
// using i+1 number of buckets.
// Final ans will be in dp[n-1, K-1]
long [, ] dp = new long[K, n];
// Corner cases
if (n < K)
return -1;
else if (n == K)
return 0;
// Filling first row, if only 1 bucket then simple count
// number of zeros and ones and do the multiplication
long zeroes = 0, ones = 0;
for (int i = 0; i < n; i++)
{
if (str[i] == '0')
zeroes++;
else
ones++;
dp[0, i] = ones * zeroes;
}
for (int s = 1; s < K; s++)
{
for (int i = 0; i < n; i++)
{
dp[s, i] = Int32.MaxValue;
ones = 0;
zeroes = 0;
for (int k = i; k >= 0; k--)
{
if (str[k] == '0')
zeroes++;
else
ones++;
// If k = 0 then this arrangement is not possible
dp[s, i] = Math.Min(dp[s, i],
+((k - 1 >= 0)
? ones * zeroes + dp[s - 1, k - 1]
: Int32.MaxValue));
}
}
}
// If no arrangement is possible then
// our answer will remain INT_MAX so return -1
return (dp[K - 1, n - 1] == Int32.MaxValue) ? -1 : dp[K - 1, n - 1];
}
// Driver code
public static void Main (string[] args)
{
string S = "0101";
// K buckets
int K = 2;
Console.WriteLine(solve(S, K));
}
}
// This code is contributed by ihritik
Javascript
2
时间复杂度: O(N 3 )
空间复杂度: O(N 2 )