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

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

给定一个由N行可变长度组成的二维数组Blocks[][] 。任务是从行的开头或结尾从Blocks[][] 中选择最多M 个具有最大可能总和的元素。

例子:

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

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

高效的方法:为了优化上述方法,想法是使用使用 Memoization 的动态规划。请按照以下步骤操作:

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

下面是上述方法的实现:

C++14
// C++ program for the above approach
#include 
using namespace std;
 
// Funtion to select 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 select 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 select 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 select 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 select 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 select 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 select 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 select
// 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


Javascript


输出:
30

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

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