📌  相关文章
📜  通过从矩阵的行的开头或结尾选择M个元素来最大化总和

📅  最后修改于: 2021-05-17 23:09:40             🧑  作者: Mango

给定2D数组, Blocks [] []N个可变长度的行组成。任务是从行的开头或结尾,从Blocks [] []中选择最多M个元素,且元素的总和最大。

例子:

天真的方法:最简单的方法是遍历矩阵的所有行,并将所有元素推入向量并对其进行排序。计算最后M个元素的总和,并将其打印为所需答案。

时间复杂度: O(N * KlogK),其中K是任何块可以具有的最大大小。
辅助空间: O(N * K)

高效方法:为了优化上述方法,其思想是使用带有记忆的动态编程。请按照以下步骤操作:

  • 给定N行和从各行,从第i行选择任何段,从说从左至右
  • i个元素的计数第i行是(R – 1 + 1),并进行到下一行。
  • 要计算最大和,请使用 前缀求和技术,以便计算总和。
  • 初始化2D数组dp [] [] ,其中dp [N] [M]通过从N行中选择最多M个元素来存储最大和。
    • 请考虑以下两种情况:
      • 要么跳过当前行。
      • 从当前行中选择不超过所选元素数的任何段。

下面是上述方法的实现:

C++14
// C++ program for the above approach
#include 
using namespace std;
 
// Funtion to selct m elements
// having maximum sum
long mElementsWithMaxSum(vector > matrix,
                         int M, int block,
                         vector > dp)
{
     
    // Base case
    if (block == matrix.size())
        return 0;
 
    // If precomputed subproblem occurred
    if (dp[block][M] != -1)
        return dp[block][M];
 
    // Either skip the current row
    long ans = mElementsWithMaxSum(matrix, M,
                                   block + 1, dp);
 
    // Iterate through all the possible
    // segments of current row
    for(int i = 0;
            i < matrix[block].size(); i++)
    {
        for(int j = i;
                j < matrix[block].size(); j++)
        {
 
            // Check if it is possible to select
            // elements from i to j
            if (j - i + 1 <= M)
            {
                 
                // Compuete the sum of i to j as
                // calculated
                ans = max(ans, matrix[block][j] -
                         ((i - 1) >= 0 ?
                         matrix[block][i - 1] : 0) +
                         mElementsWithMaxSum(matrix,
                                             M - j +
                                             i - 1,
                                         block + 1, dp));
            }
        }
    }
 
    // Store the computed answer and return
    return dp[block][M] = ans;
}
 
// Function to precompute the prefix sum
// for every row of the matrix
void preComputing(vector> matrix,
                  int N)
{
     
    // Preprocessing to calculate sum from i to j
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < matrix[i].size(); j++)
        {
            matrix[i][j] = (j > 0 ?
                  matrix[i][j - 1] : 0) +
                  matrix[i][j];
        }
    }
}
 
// Utility function to selct m elements having
// maximum sum
void mElementsWithMaxSumUtil(vector> matrix,
                             int M, int N)
{
     
    // Preprocessing step
    preComputing(matrix, N);
    long sum = 10;
     
    // Initialize dp array with -1
    vector> dp;
    dp.resize(N + 5);
    for(int i = 0; i < N + 5; i++)
        for(int j = 0; j < M + 5; j++)
            dp[i].push_back(-1);
 
    // Stores maximum sum of M elements
     sum += mElementsWithMaxSum(matrix, M,
                                0, dp);
     
    cout << sum;
}
 
// Driver Code
int main()
{
     
    // Given N
    int N = 3;
 
    // Given M
    int M = 4;
 
    // Given matrix
    vector> matrix = { { 2, 3, 5 },
                                   { -1, 7 },
                                   { 8, 10 } };
 
    // Function call
    mElementsWithMaxSumUtil(matrix, M, N);
}
 
// This code is contributed by grand_master


Java
// Java program for the above approach
 
import java.util.*;
public class GFG {
 
    // Funtion to selct m elements
    // having maximum sum
    public static long
    mElementsWithMaxSum(long[][] matrix,
                        int M, int block,
                        long[][] dp)
    {
        // Base case
        if (block == matrix.length)
            return 0;
 
        // If precomputed subproblem occurred
        if (dp[block][M] != -1)
            return dp[block][M];
 
        // Either skip the current row
        long ans
            = mElementsWithMaxSum(matrix, M,
                                block + 1, dp);
 
        // Iterate through all the possible
        // segments of current row
        for (int i = 0;
            i < matrix[block].length; i++) {
            for (int j = i;
                j < matrix[block].length; j++) {
 
                // Check if it is possible to select
                // elements from i to j
                if (j - i + 1 <= M) {
 
                    // Compuete the sum of i to j as
                    // calculated
                    ans = Math.max(
                        ans,
                        matrix[block][j]
                            - ((i - 1) >= 0
                            ? matrix[block][i - 1]
                            : 0)
                            + mElementsWithMaxSum(
                                matrix, M - j + i - 1,
                                block + 1, dp));
                }
            }
        }
 
        // Store the computed answer and return
        return dp[block][M] = ans;
    }
 
    // Function to precompute the prefix sum
    // for every row of the matrix
    public static void
    preComputing(long[][] matrix, int N)
    {
        // Preprocessing to calculate sum from i to j
        for (int i = 0;
            i < N; i++) {
            for (int j = 0;
                j < matrix[i].length; j++) {
                matrix[i][j]
                    = (j > 0
                    ? matrix[i][j - 1] : 0)
                    + matrix[i][j];
            }
        }
    }
 
    // Utility function to selct m elements having
    // maximum sum
    public static void
    mElementsWithMaxSumUtil(long[][] matrix,
                            int M, int N)
    {
        // Preprocessing step
        preComputing(matrix, N);
 
        // Initialize dp array with -1
        long dp[][] = new long[N + 5][M + 5];
        for (long i[] : dp)
            Arrays.fill(i, -1);
 
        // Stores maximum sum of M elements
        long sum = mElementsWithMaxSum(matrix, M,
                                    0, dp);
 
        // Print the sum
        System.out.print(sum);
    }
 
    // Driver Code
    public static void main(String args[])
    {
        // Given N
        int N = 3;
 
        // Given M
        int M = 4;
 
        // Given matrix
        long[][] matrix
            = { { 2, 3, 5 }, { -1, 7 },
                { 8, 10 } };
 
        // Function Call
        mElementsWithMaxSumUtil(matrix, M, N);
    }
}


Python3
# Python3 program for the above approach
 
# Funtion to selct m elements
# having maximum sum
def mElementsWithMaxSum(matrix, M, block, dp):
     
    # Base case
    if block == len(matrix):
        return 0
 
    # If precomputed subproblem occurred
    if (dp[block][M] != -1):
        return dp[block][M]
 
    # Either skip the current row
    ans = mElementsWithMaxSum(matrix, M,
                              block + 1, dp)
 
    # Iterate through all the possible
    # segments of current row
    for i in range(len(matrix[block])):
        for j in range(i, len(matrix[block])):
             
            # Check if it is possible to select
            # elements from i to j
            if (j - i + 1 <= M):
                 
                # Compuete the sum of i to j as
                # calculated
                x = 0
                if i - 1 >= 0:
                    x = matrix[block][i - 1]
                     
                ans = max(ans, matrix[block][j] - x +
                               mElementsWithMaxSum(matrix,
                                                   M - j +
                                                   i - 1,
                                               block + 1, dp))
 
    # Store the computed answer and return
    dp[block][M] = ans
     
    return ans
 
# Function to precompute the prefix sum
# for every row of the matrix
def preComputing(matrix, N):
     
    # Preprocessing to calculate sum from i to j
    for i in range(N):
        for j in range(len(matrix[i])):
            if j > 0:
                matrix[i][j] = matrix[i][j - 1]
                 
    return matrix
 
# Utility function to selct m elements having
# maximum sum
def mElementsWithMaxSumUtil(matrix, M, N):
     
    # Preprocessing step
    matrix = preComputing(matrix, N)
    sum = 20
 
    # Initialize dp array with -1
    dp = [[-1 for i in range(M + 5)]
              for i in range(N + 5)]
 
    # Stores maximum sum of M elements
    sum += mElementsWithMaxSum(matrix, M, 0, dp)
 
    print(sum)
 
# Driver Code
if __name__ == '__main__':
     
    # Given N
    N = 3
 
    # Given M
    M = 4
 
    # Given matrix
    matrix = [ [ 2, 3, 5 ],
               [ -1, 7 ],
               [ 8, 10 ] ]
 
    # Function call
    mElementsWithMaxSumUtil(matrix, M, N)
 
# This code is contributed by mohit kumar 29


C#
// C# program for
// the above approach
using System;
class GFG{
 
// Funtion to selct m elements
// having maximum sum
public static int mElementsWithMaxSum(int[,] matrix,
                                    int M, int block,
                                    int[,] dp)
{
// Base case
if (block == matrix.GetLength(0))
    return 0;
 
// If precomputed subproblem occurred
if (dp[block, M] != -1)
    return dp[block, M];
 
// Either skip the current row
int ans = mElementsWithMaxSum(matrix, M,
                                block + 1, dp);
 
// Iterate through all the possible
// segments of current row
for (int i = 0;
        i < GetRow(matrix, block).Length; i++)
{
    for (int j = i;
            j < GetRow(matrix, block).Length; j++)
    {
    // Check if it is possible to select
    // elements from i to j
    if (j - i + 1 <= M)
    {
        // Compuete the sum of i to j as
        // calculated
        ans = Math.Max(ans, matrix[block, j] -
                                ((i - 1) >= 0 ?
                            matrix[block, i - 1] : 0) +
                            mElementsWithMaxSum(matrix,
                                                M - j + i - 1,
                                                block + 1, dp));
    }
    }
}
 
// Store the computed answer and return
return dp[block, M] = ans;
}
 
// Function to precompute the prefix sum
// for every row of the matrix
public static void preComputing(int[,] matrix,
                                int N)
{
// Preprocessing to calculate sum from i to j
for (int i = 0; i < N; i++)
{
    for (int j = 0;
            j < GetRow(matrix, i).Length; j++)
    {
    matrix[i, j] = (j > 0 ? matrix[i, j - 1] : 0) +
                            matrix[i, j];
    }
}
}
 
// Utility function to selct
// m elements having maximum sum
public static void mElementsWithMaxSumUtil(int[,] matrix,
                                        int M, int N)
{
// Preprocessing step
preComputing(matrix, N);
 
// Initialize dp array with -1
int [,]dp = new int[N + 5, M + 5];
for(int i = 0; i < N + 5; i++)
{
    for (int j = 0; j < M + 5; j++)
    {
    dp[i, j] = -1;
    }
}
 
// Stores maximum sum of M elements
int sum = mElementsWithMaxSum(matrix, M,
                                0, dp);
 
// Print the sum
Console.Write(sum);
}
 
public static int[] GetRow(int[,] matrix,
                        int row)
{
var rowLength = matrix.GetLength(1);
var rowVector = new int[rowLength];
 
for (var i = 0; i < rowLength; i++)
    rowVector[i] = matrix[row, i];
 
return rowVector;
}
 
// Driver Code
public static void Main(String []args)
{
// Given N
int N = 3;
 
// Given M
int M = 4;
 
// Given matrix
int[,] matrix = {{2, 3, 5},
                {-1, 7,0},
                {8, 10, 0}};
 
// Function Call
mElementsWithMaxSumUtil(matrix, M, N);
}
}
 
// This code is contributed by Princi Singh


输出:
30









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