给定一个二进制字符串S ,任务是将序列划分为K 个非空子集,使得所有子集的0和1 出现的乘积之和最小。如果不可能打印-1。
例子:
Input: S = “0001”, K = 2
Output: 0
Explaination
We have 3 choices {0, 001}, {00, 01}, {000, 1}
The respective sum of products are {1*0 + 2*1 = 2}, {2*0 + 1*1 = 1}, {3*0 + 0*1 = 0}.
Input: S = “1011000110110100”, K = 5
Output: 8
Explanation: The subsets {10, 11, 000, 11011, 0100} minimizes the sum of product { 1*1 + 0*2 + 3*0 + 1*4 + 3*1 = 8 }.
方法:为了解决这个问题,我们使用自底向上的动态规划。
- 我们计算所有子集的最小乘积总和,然后,对于每个子集,我们使用这个值来计算该子集所有大小的最小乘积总和。
- 对于从索引i开始并在索引j结束的子集,该值将是dp[i-1] + (count_zero * count_one) 的最小值,其中count_zero和count_one分别是i和j之间出现0和1 的次数。
- 对于每个索引j ,我们在i 的所有可能值中找到最小值。
- 返回dp[N – 1]作为最终答案。
下面的代码是上述方法的实现:
C++
// C++ Program to split a given string
// into K segments such that the sum
// of product of occurence of
// characters in them is minimized
#include
using namespace std;
// Function to return the minimum
// sum of products of occurences
// of 0 and 1 in each segments
int minSumProd(string S, int K)
{
// Store the length of
// the string
int len = S.length();
// Not possible to
// generate subsets
// greater than the
// length of string
if (K > len)
return -1;
// If the number of subsets
// equals the length
if (K == len)
return 0;
vector dp(len);
int count_zero = 0, count_one = 0;
// Precompute the sum of
// products for all index
for (int j = 0; j < len; j++) {
(S[j] == '0')
? count_zero++
: count_one++;
dp[j] = count_zero * count_one;
}
// Calculate the minimum sum of
// products for K subsets
for (int i = 1; i < K; i++) {
for (int j = len; j >= i; j--) {
count_zero = 0, count_one = 0;
dp[j] = INT_MAX;
for (int k = j; k >= i; k--) {
(S[k] == '0') ? count_zero++
: count_one++;
dp[j]
= min(
dp[j],
count_zero * count_one
+ dp[k - 1]);
}
}
}
return dp[len - 1];
}
// Driver code
int main()
{
string S = "1011000110110100";
int K = 5;
cout << minSumProd(S, K) << '\n';
return 0;
}
Java
// Java Program to split a given String
// into K segments such that the sum
// of product of occurence of
// characters in them is minimized
import java.util.*;
class GFG{
// Function to return the minimum
// sum of products of occurences
// of 0 and 1 in each segments
static int minSumProd(String S, int K)
{
// Store the length of
// the String
int len = S.length();
// Not possible to
// generate subsets
// greater than the
// length of String
if (K > len)
return -1;
// If the number of subsets
// equals the length
if (K == len)
return 0;
int []dp = new int[len];
int count_zero = 0, count_one = 0;
// Precompute the sum of
// products for all index
for (int j = 0; j < len; j++)
{
if(S.charAt(j) == '0')
count_zero++;
else
count_one++;
dp[j] = count_zero * count_one;
}
// Calculate the minimum sum of
// products for K subsets
for (int i = 1; i < K; i++)
{
for (int j = len-1; j >= i; j--)
{
count_zero = 0;
count_one = 0;
dp[j] = Integer.MAX_VALUE;
for (int k = j; k >= i; k--)
{
if(S.charAt(k) == '0')
count_zero++;
else
count_one++;
dp[j] = Math.min(dp[j], count_zero *
count_one +
dp[k - 1]);
}
}
}
return dp[len - 1];
}
// Driver code
public static void main(String[] args)
{
String S = "1011000110110100";
int K = 5;
System.out.print(minSumProd(S, K));
}
}
// This code is contributed by 29AjayKumar
Python3
# Python3 program to split a given String
# into K segments such that the sum
# of product of occurence of
# characters in them is minimized
import sys
# Function to return the minimum
# sum of products of occurences
# of 0 and 1 in each segments
def minSumProd(S, K):
# Store the length of
# the String
Len = len(S);
# Not possible to
# generate subsets
# greater than the
# length of String
if (K > Len):
return -1;
# If the number of subsets
# equals the length
if (K == Len):
return 0;
dp = [0] * Len;
count_zero = 0;
count_one = 0;
# Precompute the sum of
# products for all index
for j in range(0, Len, 1):
if (S[j] == '0'):
count_zero += 1;
else:
count_one += 1;
dp[j] = count_zero * count_one;
# Calculate the minimum sum of
# products for K subsets
for i in range(1, K):
for j in range(Len - 1, i - 1, -1):
count_zero = 0;
count_one = 0;
dp[j] = sys.maxsize;
for k in range(j, i - 1, -1):
if (S[k] == '0'):
count_zero += 1;
else:
count_one += 1;
dp[j] = min(dp[j], count_zero *
count_one +
dp[k - 1]);
return dp[Len - 1];
# Driver code
if __name__ == '__main__':
S = "1011000110110100";
K = 5;
print(minSumProd(S, K));
# This code is contributed by 29AjayKumar
C#
// C# program to split a given String
// into K segments such that the sum
// of product of occurence of
// characters in them is minimized
using System;
class GFG{
// Function to return the minimum
// sum of products of occurences
// of 0 and 1 in each segments
static int minSumProd(string S, int K)
{
// Store the length of
// the String
int len = S.Length;
// Not possible to
// generate subsets
// greater than the
// length of String
if (K > len)
return -1;
// If the number of subsets
// equals the length
if (K == len)
return 0;
int []dp = new int[len];
int count_zero = 0, count_one = 0;
// Precompute the sum of
// products for all index
for(int j = 0; j < len; j++)
{
if(S[j] == '0')
{
count_zero++;
}
else
{
count_one++;
}
dp[j] = count_zero * count_one;
}
// Calculate the minimum sum
// of products for K subsets
for(int i = 1; i < K; i++)
{
for(int j = len - 1; j >= i; j--)
{
count_zero = 0;
count_one = 0;
dp[j] = Int32.MaxValue;
for(int k = j; k >= i; k--)
{
if(S[k] == '0')
{
count_zero++;
}
else
{
count_one++;
}
dp[j] = Math.Min(dp[j], count_zero *
count_one +
dp[k - 1]);
}
}
}
return dp[len - 1];
}
// Driver code
public static void Main(string[] args)
{
string S = "1011000110110100";
int K = 5;
Console.Write(minSumProd(S, K));
}
}
// This code is contributed by rutvik_56
Javascript
输出:
8
时间复杂度: O(K*N*N)
辅助空间复杂度: O(N)