📜  使用两次遍历收集网格中的最大点

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

给定一个矩阵,其中每个单元格代表点。如何在以下条件下使用两次遍历收集最大点?
让给定网格的尺寸为 R x C。
1) 第一次遍历从左上角开始,即 (0, 0),应该到达左下角,即 (R-1, 0)。第二次遍历从右上角开始,即 (0, C-1) 应该到达右下角,即 (R-1, C-1)/
2) 从点 (i, j),我们可以移动到 (i+1, j+1) or (i+1, j-1) or (i+1, j)
3) 遍历获取它经过的特定单元格的所有点。如果一次遍历已经收集了一个单元格的点,那么如果再次遍历该单元格,则另一次遍历将不会得到任何点。

Input :
    int arr[R][C] = {{3, 6, 8, 2},
                     {5, 2, 4, 3},
                     {1, 1, 20, 10},
                     {1, 1, 20, 10},
                     {1, 1, 20, 10},
                    };

     Output: 73

Explanation :

First traversal collects total points of value 3 + 2 + 20 + 1 + 1 = 27

Second traversal collects total points of value 2 + 4 + 10 + 20 + 10 = 46.
Total Points collected = 27 + 46 = 73.

我们强烈建议您将浏览器最小化,然后自己先尝试一下。
这个想法是同时进行两次遍历。我们首先从 (0, 0) 开始,同时从 (0, C-1) 开始第二次遍历。需要注意的重要一点是,在任何特定步骤中,两次遍历都将在同一行中,因为在所有可能的三个移动中,行数会增加。让 (x1, y1) 和 (x2, y2) 分别表示第一次和第二次遍历的当前位置。因此,在任何时候 x1 都将等于 x2,因为它们都向前移动,但沿 y 变化是可能的。由于 y 的变化可能以 3 种方式发生,没有变化 (y),向左 (y – 1),向右 (y + 1)。因此,y1、y2 总共有 9 种组合是可能的。基本案例之后的9个案例如下所述。

Both traversals always move forward along x
Base Cases:
// If destinations reached
if (x == R-1 && y1 == 0 && y2 == C-1)
maxPoints(arr, x, y1, y2) = arr[x][y1] + arr[x][y2];

// If any of the two locations is invalid (going out of grid)
if input is not valid
maxPoints(arr, x, y1, y2) = -INF  (minus infinite)

// If both traversals are at same cell, then we count the value of cell
// only once.
If y1 and y2 are same
    result = arr[x][y1]
Else
    result = arr[x][y1] + arr[x][y2] 

result  +=  max { // Max of 9 cases
                  maxPoints(arr, x+1, y1+1, y2),    
                  maxPoints(arr, x+1, y1+1, y2+1),
                  maxPoints(arr, x+1, y1+1, y2-1),
                  maxPoints(arr, x+1, y1-1, y2),    
                  maxPoints(arr, x+1, y1-1, y2+1),
                  maxPoints(arr, x+1, y1-1, y2-1),
                  maxPoints(arr, x+1, y1, y2),
                  maxPoints(arr, x+1, y1, y2+1),
                  maxPoints(arr, x+1, y1, y2-1) 
                }

上面的递归求解有很多子问题需要反复求解。因此,我们可以使用动态规划来更有效地解决上述问题。下面是基于记忆化(记忆化是动态编程中基于表的迭代解决方案的替代方案)的实现。在下面的实现中,我们使用记忆表“mem”来跟踪已经解决的问题。

C++
// A Memoization based program to find maximum collection
// using two traversals of a grid
#include
using namespace std;
#define R 5
#define C 4
 
// checks whether a given input is valid or not
bool isValid(int x, int y1, int y2)
{
    return (x >= 0 && x < R && y1 >=0 &&
            y1 < C && y2 >=0 && y2 < C);
}
 
// Driver function to collect max value
int getMaxUtil(int arr[R][C], int mem[R][C][C], int x, int y1, int y2)
{
    /*---------- BASE CASES -----------*/
    // if P1 or P2 is at an invalid cell
    if (!isValid(x, y1, y2)) return INT_MIN;
 
    // if both traversals reach their destinations
    if (x == R-1 && y1 == 0 && y2 == C-1)
       return (y1 == y2)? arr[x][y1]: arr[x][y1] + arr[x][y2];
 
    // If both traversals are at last row but not at their destination
    if (x == R-1) return INT_MIN;
 
    // If subproblem is already solved
    if (mem[x][y1][y2] != -1) return mem[x][y1][y2];
 
    // Initialize answer for this subproblem
    int ans = INT_MIN;
 
    // this variable is used to store gain of current cell(s)
    int temp = (y1 == y2)? arr[x][y1]: arr[x][y1] + arr[x][y2];
 
    /* Recur for all possible cases, then store and return the
       one with max value */
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2-1));
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2+1));
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2));
 
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1-1, y2));
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1-1, y2-1));
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1-1, y2+1));
 
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1+1, y2));
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1+1, y2-1));
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1+1, y2+1));
 
    return (mem[x][y1][y2] = ans);
}
 
// This is mainly a wrapper over recursive function getMaxUtil().
// This function creates a table for memoization and calls
// getMaxUtil()
int geMaxCollection(int arr[R][C])
{
    // Create a memoization table and initialize all entries as -1
    int mem[R][C][C];
    memset(mem, -1, sizeof(mem));
 
    // Calculation maximum value using memoization based function
    // getMaxUtil()
    return getMaxUtil(arr, mem, 0, 0, C-1);
}
 
// Driver program to test above functions
int main()
{
    int arr[R][C] = {{3, 6, 8, 2},
                     {5, 2, 4, 3},
                     {1, 1, 20, 10},
                     {1, 1, 20, 10},
                     {1, 1, 20, 10},
                    };
    cout << "Maximum collection is " << geMaxCollection(arr);
    return 0;
}


Java
// A Memoization based program to find maximum collection
// using two traversals of a grid
class GFG
{
     
static final int R = 5;
static final int C = 4;
 
// checks whether a given input is valid or not
static boolean isValid(int x, int y1, int y2)
{
    return (x >= 0 && x < R && y1 >=0 &&
            y1 < C && y2 >=0 && y2 < C);
}
 
// Driver function to collect Math.max value
static int getMaxUtil(int arr[][], int mem[][][],
                        int x, int y1, int y2)
{
    /*---------- BASE CASES -----------*/
    // if P1 or P2 is at an invalid cell
    if (!isValid(x, y1, y2)) return Integer.MIN_VALUE;
 
    // if both traversals reach their destinations
    if (x == R-1 && y1 == 0 && y2 == C-1)
    return (y1 == y2)? arr[x][y1]: arr[x][y1] + arr[x][y2];
 
    // If both traversals are at last
    // row but not at their destination
    if (x == R-1) return Integer.MIN_VALUE;
 
    // If subproblem is already solved
    if (mem[x][y1][y2] != -1) return mem[x][y1][y2];
 
    // Initialize answer for this subproblem
    int ans = Integer.MIN_VALUE;
 
    // this variable is used to store
    // gain of current cell(s)
    int temp = (y1 == y2)? arr[x][y1]:
                arr[x][y1] + arr[x][y2];
 
    /* Recur for all possible cases, then store
    and return the one with max value */
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1, y2-1));
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1, y2+1));
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1, y2));
 
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1-1, y2));
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1-1, y2-1));
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1-1, y2+1));
 
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1+1, y2));
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1+1, y2-1));
    ans = Math.max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1+1, y2+1));
 
    return (mem[x][y1][y2] = ans);
}
 
// This is mainly a wrapper over recursive
// function getMaxUtil(). This function
// creates a table for memoization and
// calls getMaxUtil()
static int geMaxCollection(int arr[][])
{
    // Create a memoization table and
    // initialize all entries as -1
    int [][][]mem = new int[R][C][C];
    for(int i = 0; i < R; i++)
    {
        for(int j = 0; j < C; j++)
        {
            for(int l = 0; l < C; l++)
            mem[i][j][l]=-1;
        }
    }
 
    // Calculation maximum value using memoization
    // based function getMaxUtil()
    return getMaxUtil(arr, mem, 0, 0, C-1);
}
 
// Driver code
public static void main(String[] args)
{
    int arr[][] = {{3, 6, 8, 2},
                    {5, 2, 4, 3},
                    {1, 1, 20, 10},
                    {1, 1, 20, 10},
                    {1, 1, 20, 10},
                    };
    System.out.print("Maximum collection is " +
                            geMaxCollection(arr));
    }
}
 
/* This code contributed by PrinciRaj1992 */


Python3
# A Memoization based program to find maximum collection
# using two traversals of a grid
 
R=5
C=4
intmin=-10000000
intmax=10000000
 
# checks whether a given input is valid or not
def isValid(x,y1,y2):
    return ((x >= 0 and x < R and y1 >=0
            and y1 < C and y2 >=0 and y2 < C))
 
# Driver function to collect max value
def getMaxUtil(arr,mem,x,y1,y2):
    # ---------- BASE CASES -----------
    if isValid(x, y1, y2)==False:
        return intmin
         
    # if both traversals reach their destinations
    if x == R-1 and y1 == 0 and y2 == C-1:
        if y1==y2:
            return arr[x][y1]
        else:
            return arr[x][y1]+arr[x][y2]
             
    # If both traversals are at last row
    # but not at their destination
    if x==R-1:
        return intmin
         
    # If subproblem is already solved
    if mem[x][y1][y2] != -1:
        return mem[x][y1][y2]
         
    # Initialize answer for this subproblem
    ans=intmin
 
    # this variable is used to store gain of current cell(s)
    temp=0
    if y1==y2:
        temp=arr[x][y1]
    else:
        temp=arr[x][y1]+arr[x][y2]
         
    # Recur for all possible cases, then store and return the
    # one with max value
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2-1))
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2+1))
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1, y2))
 
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1-1, y2))
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1-1, y2-1))
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1-1, y2+1))
 
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1+1, y2))
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1+1, y2-1))
    ans = max(ans, temp + getMaxUtil(arr, mem, x+1, y1+1, y2+1))
 
    mem[x][y1][y2] = ans
    return ans
 
# This is mainly a wrapper over recursive
# function getMaxUtil().
# This function creates a table for memoization and calls
# getMaxUtil()
 
def geMaxCollection(arr):
     
    # Create a memoization table and
    # initialize all entries as -1
    mem=[[[-1 for i in range(C)] for i in range(C)] for i in range(R)]
     
    # Calculation maximum value using
    # memoization based function
    # getMaxUtil()
    return getMaxUtil(arr, mem, 0, 0, C-1)
 
# Driver program to test above functions
if __name__=='__main__':
    arr=[[3, 6, 8, 2],
        [5, 2, 4, 3],
        [1, 1, 20, 10],
        [1, 1, 20, 10],
        [1, 1, 20, 10],
        ]
    print('Maximum collection is ', geMaxCollection(arr))
     
#this code is contributed by sahilshelangia


C#
// A Memoization based program to find maximum collection
// using two traversals of a grid
using System;
 
class GFG
{
     
static readonly int R = 5;
static readonly int C = 4;
 
// checks whether a given input is valid or not
static bool isValid(int x, int y1, int y2)
{
    return (x >= 0 && x < R && y1 >=0 &&
            y1 < C && y2 >=0 && y2 < C);
}
 
// Driver function to collect Math.max value
static int getMaxUtil(int [,]arr, int [,,]mem,
                        int x, int y1, int y2)
{
    /*---------- BASE CASES -----------*/
    // if P1 or P2 is at an invalid cell
    if (!isValid(x, y1, y2)) return int.MinValue;
 
    // if both traversals reach their destinations
    if (x == R-1 && y1 == 0 && y2 == C-1)
    return (y1 == y2)? arr[x, y1]: arr[x, y1] + arr[x, y2];
 
    // If both traversals are at last
    // row but not at their destination
    if (x == R-1) return int.MinValue;
 
    // If subproblem is already solved
    if (mem[x, y1, y2] != -1) return mem[x, y1, y2];
 
    // Initialize answer for this subproblem
    int ans = int.MinValue;
 
    // this variable is used to store
    // gain of current cell(s)
    int temp = (y1 == y2)? arr[x, y1]:
                arr[x, y1] + arr[x, y2];
 
    /* Recur for all possible cases, then store
    and return the one with max value */
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1, y2-1));
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1, y2+1));
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1, y2));
 
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1-1, y2));
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1-1, y2-1));
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1-1, y2+1));
 
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1+1, y2));
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1+1, y2-1));
    ans = Math.Max(ans, temp +
            getMaxUtil(arr, mem, x+1, y1+1, y2+1));
 
    return (mem[x, y1, y2] = ans);
}
 
// This is mainly a wrapper over recursive
// function getMaxUtil(). This function
// creates a table for memoization and
// calls getMaxUtil()
static int geMaxCollection(int [,]arr)
{
    // Create a memoization table and
    // initialize all entries as -1
    int [,,]mem = new int[R, C, C];
    for(int i = 0; i < R; i++)
    {
        for(int j = 0; j < C; j++)
        {
            for(int l = 0; l < C; l++)
            mem[i, j, l]=-1;
        }
    }
 
    // Calculation maximum value using memoization
    // based function getMaxUtil()
    return getMaxUtil(arr, mem, 0, 0, C-1);
}
 
// Driver code
public static void Main(String[] args)
{
    int [,]arr = {{3, 6, 8, 2},
                    {5, 2, 4, 3},
                    {1, 1, 20, 10},
                    {1, 1, 20, 10},
                    {1, 1, 20, 10},
                    };
    Console.Write("Maximum collection is " +
                            geMaxCollection(arr));
    }
}
 
// This code contributed by Rajput-Ji


Javascript


输出:

Maximum collection is 73

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