给定由整数组成的 n 个不同长度的数组,目标是从数组中选取最多一个子数组,使得所有选取的子数组的组合长度不大于 m,并且它们的元素之和最大。(也给定该值n 不能超过 100)
先决条件:背包问题
例子 :
Input :
n = 5, m = 6
arr[][m] = {{3, 2, 3, 5},
{2, 7, -1},
{2, 8, 10},
{4, 5, 2, 6, 1},
{3, 2, 3, -2}};
Output : Maximum sum can be obtained is 39
Explanation : We are allowed to pick at most
one subarray from every array.
We get total sum 39 as ((5) + (7) + (8 + 10) +
(4 + 5))
Input :
n = 3, m = 4
arr[][m] = {{2, 3, 2},
{3, -1, 7, 10},
{4, 8, 10, -5, 3}};
Output : Maximum sum can be obtained is 35
这个问题类似于背包问题。你要么选择一个元素,要么离开它。我们将在这里采用相同的策略。
鉴于这 n 个数组中的元素总数最多为 10^5。众所周知,m 最多为 10^3,输入数组可以包含负数。首先,制作一个大小为 n * m 的 DP 表(二维数组),然后,预先计算数组的累积和,以便可以轻松计算该数组从 1 到 n 的每个长度的最大和,以便对于每个给定数组,长度 k 可以有最大连续和,其中 k 是从 1 到数组长度。
详细地,将输入数组一一处理。首先,计算从 1 到 length 的所有大小的已处理数组的最大和子数组。然后,用这些值更新我们的动态规划表,我们开始处理下一个数组。
算法 :
- 从 n 个数组中选择一个数组并开始处理它。
- 计算长度为 k 的最大连续和,k 是从 1 到数组的长度,并将其保存在数组 maxSum 中。
- 现在,通过存储每个长度 0 到 m 的最大和来填充 DP 表。
- 在最后一步中,我们遍历 DP 表的最后一行(第 n 行)并选择可能的最大和并将其返回。
以下是上述方法的实现:
C++
// A Dynamic Programming based C++ program to find // maximum sum of array of size less than or // equal to m from given n arrays #include
using namespace std; /* N and M to define sizes of arr, dp, current_arr and maxSum */ #define N 105 #define M 1001 // INF to define min value #define INF -1111111111 // Function to find maximum sum int maxSum(int arr[][N]) { // dp array of size N x M int dp[N][M]; // current_arr of size M int current_arr[M]; // maxsum of size M int maxsum[M]; memset(dp, -1, sizeof(dp[0][0]) * N * M); current_arr[0] = 0; // if we have 0 elements // from 0th array dp[0][0] = 0; for (int i = 1; i <= 5; i++) { int len = arr[i - 1][0]; // compute the cumulative sum array for (int j = 1; j <= len; j++) { current_arr[j] = arr[i - 1][j]; current_arr[j] += current_arr[j - 1]; maxsum[j] = INF; } // calculating the maximum contiguous // array for every length j, j is from // 1 to lengtn of the array for (int j = 1; j <= len && j <= 6; j++) for (int k = 1; k <= len; k++) if (j + k - 1 <= len) maxsum[j] = max(maxsum[j], current_arr[j + k - 1] - current_arr[k - 1]); // every state is depending on // its previous state for (int j = 0; j <= 6; j++) dp[i][j] = dp[i - 1][j]; // computation of dp table similar // approach as knapsack problem for (int j = 1; j <= 6; j++) for (int cur = 1; cur <= j && cur <= len; cur++) dp[i][j] = max(dp[i][j], dp[i - 1][j - cur] + maxsum[cur]); } // now we have done processing with // the last array lets find out // what is the maximum sum possible int ans = 0; for (int i = 0; i <= 6; i++) ans = max(ans, dp[5][i]); return ans; } // Driver program int main() { // first element of each // row is the size of that row int arr[][N] = { { 3, 2, 3, 5 }, { 2, 7, -1 }, { 2, 8, 10 }, { 4, 5, 2, 6, 1 }, { 3, 2, 3, -2 } }; cout << "Maximum sum can be obtained " << "is : " << maxSum(arr) << "\n"; }
Java
// Java program to find maximum sum // of array of size less than or // equal to m from given n arrays import java.io.*; public class GFG { /* N and M to define sizes of arr, dp, current_arr and maxSum */ static int N = 105; static int M = 1001; // INF to define // min value static int INF = -1111111111; // Function to find // maximum sum static int maxSum(int [][]arr) { // dp array of size N x M int [][]dp = new int[N][M]; // current_arr of size M int []current_arr = new int[M]; // maxsum of size M int []maxsum = new int[M]; for (int i = 0; i < N; i++) { for (int j = 0; j < M ; j++) dp[i][j] = -1; } current_arr[0] = 0; // if we have 0 elements // from 0th array dp[0][0] = 0; for (int i = 1; i <= 5; i++) { int len = arr[i - 1][0]; // compute the cumulative // sum array for (int j = 1; j <= len; j++) { current_arr[j] = arr[i - 1][j]; current_arr[j] += current_arr[j - 1]; maxsum[j] = INF; } // calculating the maximum // contiguous array for every // length j, j is from 1 to // lengtn of the array for (int j = 1; j <= len && j <= 6; j++) for (int k = 1; k <= len; k++) if (j + k - 1 <= len) maxsum[j] = Math.max(maxsum[j], current_arr[j + k - 1] - current_arr[k - 1]); // every state is depending // on its previous state for (int j = 0; j <= 6; j++) dp[i][j] = dp[i - 1][j]; // computation of dp table // similar approach as // knapsack problem for (int j = 1; j <= 6; j++) for (int cur = 1; cur <= j && cur <= len; cur++) dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - cur] + maxsum[cur]); } // now we have done processing // with the last array lets // find out what is the maximum // sum possible int ans = 0; for (int i = 0; i <= 6; i++) ans = Math.max(ans, dp[5][i]); return ans; } // Driver Code public static void main(String args[]) { // first element of each // row is the size of that row int[][] arr = { { 3, 2, 3, 5 }, { 2, 7, -1 }, { 2, 8, 10 }, { 4, 5, 2, 6, 1 }, { 3, 2, 3, -2 } }; System.out.println("Maximum sum can be " + "obtained is : " + maxSum(arr)); } } // This code is contributed by // Manish Shaw(manishshaw1)
Python3
# A Dynamic Programming based Python3 # program to find maximum sum of array # of size less than or equal to m from # given n arrays # N and M to define sizes of arr, # dp, current_arr and maxSum N = 105 M = 1001 # INF to define min value INF = -1111111111 # Function to find maximum sum def maxSum(arr): # dp array of size N x M dp = [[-1 for x in range(M)] for y in range(N)] # current_arr of size M current_arr = [0] * M # maxsum of size M maxsum = [0] * M current_arr[0] = 0 # If we have 0 elements # from 0th array dp[0][0] = 0 for i in range(1, 6): len = arr[i - 1][0] # Compute the cumulative sum array for j in range(1, len + 1): current_arr[j] = arr[i - 1][j] current_arr[j] += current_arr[j - 1] maxsum[j] = INF # Calculating the maximum contiguous # array for every length j, j is from # 1 to lengtn of the array j = 1 while j <= len and j <= 6: for k in range(1, len + 1): if (j + k - 1 <= len): maxsum[j] = max(maxsum[j], current_arr[j + k - 1] - current_arr[k - 1]) j += 1 # Every state is depending on # its previous state for j in range(7): dp[i][j] = dp[i - 1][j] # computation of dp table similar # approach as knapsack problem for j in range(1, 7): cur = 1 while cur <= j and cur <= len: dp[i][j] = max(dp[i][j], dp[i - 1][j - cur] + maxsum[cur]) cur += 1 # Now we have done processing with # the last array lets find out # what is the maximum sum possible ans = 0 for i in range(7): ans = max(ans, dp[5][i]) return ans # Driver code if __name__ == "__main__": # First element of each # row is the size of that row arr = [ [ 3, 2, 3, 5 ], [ 2, 7, -1 ], [ 2, 8, 10 ], [ 4, 5, 2, 6, 1 ], [ 3, 2, 3, -2 ] ] print("Maximum sum can be obtained", "is : ", maxSum(arr)) # This code is contributed by chitranayal
C#
// C# program to find maximum sum // of array of size less than or // equal to m from given n arrays using System; class GFG { /* N and M to define sizes of arr, dp, current_arr and maxSum */ static int N = 105; static int M = 1001; // INF to define // min value static int INF = -1111111111; // Function to find // maximum sum static int maxSum(int [][]arr) { // dp array of size N x M int [,]dp = new int[N, M]; // current_arr of size M int []current_arr = new int[M]; // maxsum of size M int []maxsum = new int[M]; for (int i = 0; i < N; i++) { for (int j = 0; j < M ; j++) dp[i, j] = -1; } current_arr[0] = 0; // if we have 0 elements // from 0th array dp[0, 0] = 0; for (int i = 1; i <= 5; i++) { int len = arr[i - 1][0]; // compute the cumulative // sum array for (int j = 1; j <= len; j++) { current_arr[j] = arr[i - 1][j]; current_arr[j] += current_arr[j - 1]; maxsum[j] = INF; } // calculating the maximum // contiguous array for every // length j, j is from 1 to // lengtn of the array for (int j = 1; j <= len && j <= 6; j++) for (int k = 1; k <= len; k++) if (j + k - 1 <= len) maxsum[j] = Math.Max(maxsum[j], current_arr[j + k - 1] - current_arr[k - 1]); // every state is depending // on its previous state for (int j = 0; j <= 6; j++) dp[i, j] = dp[i - 1, j]; // computation of dp table // similar approach as // knapsack problem for (int j = 1; j <= 6; j++) for (int cur = 1; cur <= j && cur <= len; cur++) dp[i, j] = Math.Max(dp[i, j], dp[i - 1, j - cur] + maxsum[cur]); } // now we have done processing // with the last array lets // find out what is the maximum // sum possible int ans = 0; for (int i = 0; i <= 6; i++) ans = Math.Max(ans, dp[5, i]); return ans; } // Driver Code static void Main() { // first element of each // row is the size of that row int[][] arr = new int[][] { new int[]{ 3, 2, 3, 5 }, new int[]{ 2, 7, -1 }, new int[]{ 2, 8, 10 }, new int[]{ 4, 5, 2, 6, 1 }, new int[]{ 3, 2, 3, -2 } }; Console.Write ("Maximum sum can be " + "obtained is : " + maxSum(arr) + "\n"); } } // This code is contributed by // Manish Shaw(manishshaw1)
输出 :Maximum sum can be obtained is : 39
时间复杂度: O( n)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。