📌  相关文章
📜  将数组划分为 K 段,使最小值的总和最大化

📅  最后修改于: 2021-09-22 09:52:24             🧑  作者: Mango

给定的大小N和整数K,阵列,则任务是将阵列分成K个片段使得最小K个片段中的总和被最大化分裂。
例子:

方法:这个问题可以使用动态规划来解决。使用递归尝试所有可能的分区。令dp[i][k]是直到索引 i 与 k 个分区的最小值的最大总和。因此,可能的状态将在从索引 i 到 n 的每个索引处进行分区。所有这些状态的最小值的最大总和将是我们的答案。写完这个递归后,我们就可以使用memorize了。

下面是上述方法的实现:

C++
// C++ program to find the sum of
// the minimum of all the segments
#include 
using namespace std;
const int MAX = 10;
 
// Function to maximize the sum of the minimums
int maximizeSum(int a[], int n, int ind,
                int k, int dp[MAX][MAX])
{
 
    // If k segments have been divided
    if (k == 0) {
        // If we are at the end
        if (ind == n)
            return 0;
 
        // If we donot reach the end
        // then return a negative number
        // that cannot be the sum
        else
            return -1e9;
    }
 
    // If at the end but
    // k segments are not formed
    else if (ind == n)
        return -1e9;
 
    // If the state has not been visited yet
    else if (dp[ind][k] != -1)
        return dp[ind][k];
 
    // If the state has not been visited
    else {
        int ans = 0;
 
        // Get the minimum element in the segment
        int mini = a[ind];
 
        // Iterate and try to break at every index
        // and create a segment
        for (int i = ind; i < n; i++) {
 
            // Find the minimum element in the segment
            mini = min(mini, a[i]);
 
            // Find the sum of all the segments trying all
            // the possible combinations
            ans = max(ans, maximizeSum(
              a, n, i + 1, k - 1, dp) + mini);
        }
 
        // Return the answer by
        // memoizing it
        return dp[ind][k] = ans;
    }
}
 
// Driver Code
int main()
{
    int a[] = { 5, 7, 4, 2, 8, 1, 6 };
    int k = 3;
    int n = sizeof(a) / sizeof(a[0]);
 
    // Initialize dp array with -1
    int dp[MAX][MAX];
    memset(dp, -1, sizeof dp);
 
    cout << maximizeSum(a, n, 0, k, dp);
 
    return 0;
}


Java
// Java program to find the sum of
// the minimum of all the segments
 
class GFG
{
 
    static int MAX = 10;
 
    // Function to maximize the
    // sum of the minimums
    public static int maximizeSum(
              int[] a, int n, int ind,
                 int k, int[][] dp)
    {
        // If k segments have been divided
        if (k == 0)
        {
            // If we are at the end
            if (ind == n)
                return 0;
 
            // If we donot reach the end
            // then return a negative number
            // that cannot be the sum
            else
                return -1000000000;
        }
 
        // If at the end but
        // k segments are not formed
        else if (ind == n)
            return -1000000000;
 
        // If the state has not
        // been visited yet
        else if (dp[ind][k] != -1)
            return dp[ind][k];
 
        // If the state has
        // not been visited
        else
        {
            int ans = 0;
 
            // Get the minimum
            // element in the segment
            int mini = a[ind];
 
            // Iterate and try to break
            // at every index
            // and create a segment
            for (int i = ind; i < n; i++)
            {
 
                // Find the minimum element
                // in the segment
                mini = Math.min(mini, a[i]);
 
                // Find the sum of all the
                // segments trying all
                // the possible combinations
                ans = Math.max(ans,
                     maximizeSum(a, n, i + 1,
                           k - 1, dp) + mini);
            }
 
            // Return the answer by
            // memoizing it
            return dp[ind][k] = ans;
        }
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int[] a = { 5, 7, 4, 2, 8, 1, 6 };
        int k = 3;
        int n = a.length;
 
        // Initialize dp array with -1
        int[][] dp = new int[MAX][MAX];
        for (int i = 0; i < MAX; i++)
        {
            for (int j = 0; j < MAX; j++)
                dp[i][j] = -1;
        }
 
        System.out.println(
          maximizeSum(a, n, 0, k, dp));
    }
}
 
// This code is contributed by
// sanjeev2552


Python3
# Python 3 program to find the sum of
# the minimum of all the segments
MAX = 10
 
# Function to maximize the
# sum of the minimums
def maximizeSum(a,n, ind, k, dp):
    # If k segments have been divided
    if (k == 0):
        # If we are at the end
        if (ind == n):
            return 0
 
        # If we donot reach the end
        # then return a negative number
        # that cannot be the sum
        else:
            return -1e9
 
    # If at the end but
    # k segments are not formed
    elif (ind == n):
        return -1e9
 
    # If the state has been visited already
    elif (dp[ind][k] != -1):
        return dp[ind][k]
 
    # If the state has not been visited
    else:
        ans = 0
 
        # Get the minimum element
        # in the segment
        mini = a[ind]
 
        # Iterate and try to break
        # at every index
        # and create a segment
        for i in range(ind,n,1):
            # Find the minimum element
            # in the segment
            mini = min(mini, a[i])
 
            # Find the sum of all the
            # segments trying all
            # the possible combinations
            ans = max(ans, maximizeSum(\
             a, n, i + 1, k - 1, dp) + mini)
 
        # Return the answer by
        # memoizing it
        dp[ind][k] = ans
        return ans
         
# Driver Code
if __name__ == '__main__':
    a = [5, 7, 4, 2, 1, 6]
    k = 3
    n = len(a)
 
    # Initialize dp array with -1
    dp = [[-1 for i in range(MAX)]\
          for j in range(MAX)]
 
    print(maximizeSum(a, n, 0, k, dp))
 
# This code is contributed by
# Surendra_Gangwar


C#
// C# program to find the sum of
// the minimum of all the segments
using System;
     
class GFG
{
    static int MAX = 10;
 
    // Function to maximize the sum of the minimums
    public static int maximizeSum(
             int[] a, int n, int ind,
                  int k, int[] dp)
    {
        // If k segments have been divided
        if (k == 0)
        {
            // If we are at the end
            if (ind == n)
                return 0;
 
            // If we donot reach the end
            // then return a negative number
            // that cannot be the sum
            else
                return -1000000000;
        }
 
        // If at the end but
        // k segments are not formed
        else if (ind == n)
            return -1000000000;
 
        // If the state has not
        // been visited yet
        else if (dp[ind, k] != -1)
            return dp[ind, k];
 
        // If the state has not been visited
        else
        {
            int ans = 0;
 
            // Get the minimum element
            // in the segment
            int mini = a[ind];
 
            // Iterate and try to break
            // at every index
            // and create a segment
            for (int i = ind; i < n; i++)
            {
 
                // Find the minimum element
                // in the segment
                mini = Math.Min(mini, a[i]);
 
                // Find the sum of all the
                // segments trying all
                // the possible combinations
                ans = Math.Max(ans,
                      maximizeSum(a, n, i + 1,
                           k - 1, dp) + mini);
            }
 
            // Return the answer by
            // memoizing it
            return dp[ind,k] = ans;
        }
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int[] a = { 5, 7, 4, 2, 8, 1, 6 };
        int k = 3;
        int n = a.Length;
 
        // Initialize dp array with -1
        int[,] dp = new int[MAX, MAX];
        for (int i = 0; i < MAX; i++)
        {
            for (int j = 0; j < MAX; j++)
                dp[i, j] = -1;
        }
 
        Console.WriteLine(
          maximizeSum(a, n, 0, k, dp));
    }
}
 
// This code is contributed by 29AjayKumar


Javascript


输出

13

时间复杂度:O(N * N * K)
辅助空间:O(N * K)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程