最多可以从一行中选择 K 个元素时的最大路径和
给定一个大小为N * M的矩阵mat [][] 和一个整数K ,任务是找到从左上角单元格(0, 0 ) 到右下角单元格 ( N–1, M–1 ) 的路径)的给定矩阵,使得:
- 允许一次向右和向下移动。即,从(i,j)到(i,j-1)和(i+1,j)。
- 路径中元素的总和最大,并且可以从一行中选择不超过 K 个单元格。
例子:
Input: N = 3, M = 3, K = 2, mat = [[2, 10, 8], [8, 8, 8], [0, 1, 0]]
Output: 28
Explanation: The optimal way of choosing cells will be (0, 0) -> (0, 1) -> (1, 1) -> (1, 2) -> (2, 2).
Input: N = 3, M = 3, K = 1, mat = [[0, 0, 4], [0, 5, 0], [3, 0, 2]]
Output: 7
Explanation: The optimal way of choosing cells will be (0, 0) -> (1, 0) -> (1, 1) -> (1, 2) -> (2, 2).
朴素方法:最简单的方法是找到从左上角到右下角的所有可能路径,并且单行中的单元格不超过K。计算它们之间的最大路径和。
时间复杂度: O( M+N-2 C N-1 )
辅助空间: O(1)
有效的方法:解决问题的有效方法是使用基于以下思想的动态规划:
For any row consider that 1 to K number of elements are chosen from that row.
For any cell (i, j) consider it to be a part of the path choosing l number of cells from that row.
Create a 3D dp array where dp[i][j][l] store the calculated value when cell (i, j) is part of a path having l cells from that row.
- dp[i][j][l] depends on dp[i][j][l-1] and dp[i][j-1][l].
- dp[i][j][0] depends on dp[i-1][j][l] for all value of l from 1 to K (because when row is changed no element from the new row is taken till now).
请按照以下步骤解决此问题:
- 声明一个 3D 数组(比如dp ) 大小为N * M * (K + 1) 。
- 迭代给定的矩阵:
- 以相反的顺序迭代l的所有可能值(从K-1 到 0 ):
- 检查dp的当前状态是否为正值。
- 然后更新第 (l + 1) 个状态的dp数组,因为我们包含了网格的当前值。
- 再次遍历l的所有可能值:
- 检查dp的当前状态是否为正值。
- 然后更新当前单元格的向下单元格(如果存在)。
- 如果存在,还更新当前单元格的右侧单元格。
- 以相反的顺序迭代l的所有可能值(从K-1 到 0 ):
- 声明一个整数变量ans并将其初始化为 0。
- 遍历l的所有可能值。
- 将ans更新为自身的最大值和 dp[N-1][M-1][l]。
- 最后,返回ans 。
以下是上述方法的实现:
C++
// C++ code to implement the approach
#include
using namespace std;
// Function to find the maximum path sum
int maximumProfits(int n, int m, int k,
vector >& grid)
{
// Declare a -d array named “dp”
// with size ‘N’ * ‘M’ * (‘K’ + 1).
int dp[n][m][k + 1];
// Initialize the "dp" array with INT_MIN.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int l = 0; l < k + 1; l++) {
dp[i][j][l] = INT_MIN;
}
}
}
// Base case.
dp[0][0][0] = 0;
// Iterate over the grid.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
// Iterate over the possible
// values of ‘l’ in reverse order.
for (int l = k - 1; l >= 0; l--) {
// If the current state
// of “dp” has positive value
if (dp[i][j][l] >= 0) {
// Update “dp” array for
//(‘l’ + 1)-th state since
// we include
// the current value
// of the grid.
dp[i][j][l + 1]
= max(dp[i][j][l + 1],
dp[i][j][l]
+ grid[i][j]);
}
}
// Again iterate over
// all possible values of ‘l’.
for (int l = 0; l < k + 1; l++) {
// If the current state
// of “dp” has positive value
if (dp[i][j][l] >= 0) {
// Update the downward cell
// of the current cell
// if it exists.
if (i + 1 < n) {
dp[i + 1][j][0] = max(
dp[i + 1][j][0],
dp[i][j][l]);
}
// Update the right cell
// of the current cell
// if it exists.
if (j + 1 < m) {
dp[i][j + 1][l] = max(
dp[i][j + 1][l],
dp[i][j][l]);
}
}
}
}
}
// Declare an integer variable “ans” and
// initialize it with 0.
int ans = 0;
// Iterate over all possible values of l
for (int l = 0; l < k + 1; l++) {
// Update ans as max of itself and
// the dp value for (n -1, m - 1)th
// cell for the current value of l
ans = max(ans, dp[n - 1][m - 1][l]);
}
// Return the “ans”.
return ans;
}
// Driver code
int main()
{
int N = 3, M = 3, K = 2;
vector > mat = { { 2, 10, 8 },
{ 8, 8, 8 },
{ 0, 1, 0 } };
cout << maximumProfits(N, M, K, mat);
return 0;
}
Java
// JAVA code to implement the approach
import java.util.*;
class GFG {
// Function to find the maximum path sum
public static int
maximumProfits(int n, int m, int k,
ArrayList > grid)
{
// Declare a -d array named “dp”
// with size ‘N’ * ‘M’ * (‘K’ + 1).
int dp[][][] = new int[n][m][k + 1];
// Initialize the "dp" array with INT_MIN.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int l = 0; l < k + 1; l++) {
dp[i][j][l] = Integer.MIN_VALUE;
}
}
}
// Base case.
dp[0][0][0] = 0;
// Iterate over the grid.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
// Iterate over the possible
// values of ‘l’ in reverse order.
for (int l = k - 1; l >= 0; l--) {
// If the current state
// of “dp” has positive value
if (dp[i][j][l] >= 0) {
// Update “dp” array for
//(‘l’ + 1)-th state since
// we include
// the current value
// of the grid.
dp[i][j][l + 1] = Math.max(
dp[i][j][l + 1],
dp[i][j][l]
+ grid.get(i).get(j));
}
}
// Again iterate over
// all possible values of ‘l’.
for (int l = 0; l < k + 1; l++) {
// If the current state
// of “dp” has positive value
if (dp[i][j][l] >= 0) {
// Update the downward cell
// of the current cell
// if it exists.
if (i + 1 < n) {
dp[i + 1][j][0]
= Math.max(dp[i + 1][j][0],
dp[i][j][l]);
}
// Update the right cell
// of the current cell
// if it exists.
if (j + 1 < m) {
dp[i][j + 1][l]
= Math.max(dp[i][j + 1][l],
dp[i][j][l]);
}
}
}
}
}
// Declare an integer variable “ans” and
// initialize it with 0.
int ans = 0;
// Iterate over all possible values of l
for (int l = 0; l < k + 1; l++) {
// Update ans as max of itself and
// the dp value for (n -1, m - 1)th
// cell for the current value of l
ans = Math.max(ans, dp[n - 1][m - 1][l]);
}
// Return the “ans”.
return ans;
}
// Driver code
public static void main(String[] args)
{
int N = 3, M = 3, K = 2;
ArrayList > mat
= new ArrayList >();
ArrayList temp1 = new ArrayList(
Arrays.asList(2, 10, 8));
ArrayList temp2 = new ArrayList(
Arrays.asList(8, 8, 8));
ArrayList temp3 = new ArrayList(
Arrays.asList(0, 1, 0));
mat.add(temp1);
mat.add(temp2);
mat.add(temp3);
System.out.print(maximumProfits(N, M, K, mat));
}
}
// This code is contributed by Taranpreet
Python3
# Python code to implement the approach
import sys
INT_MIN = -sys.maxsize - 1
# Function to find the maximum path sum
def maximumProfits(n, m, k,grid):
global INT_MIN
# Declare a -d array named “dp”
# with size ‘N’ * ‘M’ * (‘K’ + 1).
# Initialize the "dp" array with INT_MIN.
dp = [[[INT_MIN for i in range(k + 1)] for j in range(m)] for l in range(n)]
# Base case.
dp[0][0][0] = 0
# Iterate over the grid.
for i in range(n):
for j in range(m):
# Iterate over the possible
# values of ‘l’ in reverse order.
for l in range(k - 1,-1,-1):
# If the current state
# of “dp” has positive value
if (dp[i][j][l] >= 0):
# Update “dp” array for
#(‘l’ + 1)-th state since
# we include
# the current value
# of the grid.
dp[i][j][l + 1] = max(dp[i][j][l + 1],dp[i][j][l] + grid[i][j])
# Again iterate over
# all possible values of ‘l’.
for l in range(k + 1):
# If the current state
# of “dp” has positive value
if (dp[i][j][l] >= 0):
# Update the downward cell
# of the current cell
# if it exists.
if (i + 1 < n):
dp[i + 1][j][0] = max(dp[i + 1][j][0],dp[i][j][l])
# Update the right cell
# of the current cell
# if it exists.
if (j + 1 < m):
dp[i][j + 1][l] = max(dp[i][j + 1][l],dp[i][j][l])
# Declare an integer variable “ans” and
# initialize it with 0.
ans = 0
# Iterate over all possible values of l
for l in range(k + 1):
# Update ans as max of itself and
# the dp value for (n -1, m - 1)th
# cell for the current value of l
ans = max(ans, dp[n - 1][m - 1][l])
# Return the “ans”.
return ans
# Driver code
N, M, K = 3, 3, 2
mat = [ [ 2, 10, 8 ],[ 8, 8, 8 ],[ 0, 1, 0 ] ]
print(maximumProfits(N, M, K, mat))
# This code is contributed by shinjanpatra.
C#
// C# code to implement the approach
using System;
using System.Collections.Generic;
public class GFG{
// Function to find the maximum path sum
static int
maximumProfits(int n, int m, int k,
List > grid)
{
// Declare a -d array named “dp”
// with size ‘N’ * ‘M’ * (‘K’ + 1).
int[, ,] dp = new int[n,m,k + 1];
// Initialize the "dp" array with INT_MIN.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int l = 0; l < k + 1; l++) {
dp[i, j, l] = Int32.MinValue;
}
}
}
// Base case.
dp[0,0,0] = 0;
// Iterate over the grid.
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
// Iterate over the possible
// values of ‘l’ in reverse order.
for (int l = k - 1; l >= 0; l--) {
// If the current state
// of “dp” has positive value
if (dp[i,j,l] >= 0) {
// Update “dp” array for
//(‘l’ + 1)-th state since
// we include
// the current value
// of the grid.
dp[i, j,l+1] = Math.Max(
dp[i, j,l+1],
dp[i, j,l]
+ grid[i][j]);
}
}
// Again iterate over
// all possible values of ‘l’.
for (int l = 0; l < k + 1; l++) {
// If the current state
// of “dp” has positive value
if (dp[i,j,l] >= 0) {
// Update the downward cell
// of the current cell
// if it exists.
if (i + 1 < n) {
dp[i + 1,j,0]
= Math.Max(dp[i + 1,j,0],
dp[i,j,l]);
}
// Update the right cell
// of the current cell
// if it exists.
if (j + 1 < m) {
dp[i,j + 1,l]
= Math.Max(dp[i,j + 1,l],
dp[i,j, l]);
}
}
}
}
}
// Declare an integer variable “ans” and
// initialize it with 0.
int ans = 0;
// Iterate over all possible values of l
for (int l = 0; l < k + 1; l++) {
// Update ans as max of itself and
// the dp value for (n -1, m - 1)th
// cell for the current value of l
ans = Math.Max(ans, dp[n - 1,m - 1,l]);
}
// Return the “ans”.
return ans;
}
// Driver code
static public void Main (){
int N = 3, M = 3, K = 2;
List> mat = new List>();
mat.Add(new List {2, 10, 8 });
mat.Add(new List { 8, 8, 8 });
mat.Add(new List { 0, 1, 0 });
Console.Write(maximumProfits(N, M, K, mat));
}
}
// This code is contributed by hrithikgarg03188.
Javascript
28
时间复杂度: O (N * M * K)
辅助空间: O(N * M * K)