📌  相关文章
📜  将二进制字符串拆分为 K 个子集,以最小化 0 和 1 出现的乘积之和

📅  最后修改于: 2021-09-22 09:38:13             🧑  作者: Mango

给定一个二进制字符串S ,任务是将序列划分为K 个非空子集,使得所有子集的01 出现的乘积之和最小。如果不可能打印-1。
例子:

方法:为了解决这个问题,我们使用自底向上的动态规划。

  • 我们计算所有子集的最小乘积总和,然后,对于每个子集,我们使用这个值来计算该子集所有大小的最小乘积总和。
  • 对于从索引i开始并在索引j结束的子集,该值将是dp[i-1] + (count_zero * count_one) 的最小值,其中count_zerocount_one分别是ij之间出现01 的次数
  • 对于每个索引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)