# Collect maximum points in a grid using two traversals – GeeksforGeeks

Given a matrix where every cell represents points. How to collect utmost points using two traversals under following conditions ?
Let the dimensions of given grid be R x C.
1 ) The first traversal starts from top leave corner, i.e., ( 0, 0 ) and should reach left bottomland corner, i.e., ( R-1, 0 ). The second traversal starts from crown right corner, i.e., ( 0, C-1 ) and should reach bottom right corner, i.e., ( R-1, C-1 ) /
2 ) From a luff ( iodine, j ), we can move to ( i+1, j+1 ) or ( i+1, j-1 ) or ( i+1, j )
3 ) A traversal gets all points of a especial cell through which it passes. If one traversal has already collected points of a cell, then the other traversal gets no points if goes through that cell again.

```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.```

We strongly recommend you to minimize your browser and try this yourself first.
The idea is to do both traversals concurrently. We start first from ( 0, 0 ) and second traversal from ( 0, C-1 ) simultaneously. The important thing to note is, at any particular step both traversals will be in same row as in all potential three moves, row number is increased. Let ( x1, y1 ) and ( x2, y2 ) denote current positions of first and second base traversals respectively. frankincense at any clock time x1 will be equal to x2 as both of them move forward but variation is possible along y. Since variation in y could occur in 3 ways no switch ( yttrium ), go left ( y – 1 ), go good ( y + 1 ). so in full 9 combinations among y1, y2 are possible. The 9 cases as mentioned below after base cases.

```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)
}```

The above recursive solution has many subproblems that are solved again and again. consequently, we can use Dynamic Programming to solve the above problem more efficiently. Below is memoization ( Memoization is option to table based iterative solution in Dynamic Programming ) based implementation. In below execution, we use a memoization table ‘ mem ’ to keep track of already solved problems.

## C++

 `#include` `using` `namespace` `std;` `#define R 5` `#define C 4` `bool` `isValid(` `int` `x, ` `int` `y1, ` `int` `y2)` `{` `    ` `return` `(x >= 0 && x < R && y1 >=0 &&` `            ` `y1 < C && y2 >=0 && y2 < C);` `}` `int` `getMaxUtil(` `int` `arr[R][C], ` `int` `mem[R][C][C], ` `int` `x, ` `int` `y1, ` `int` `y2)` `{` `    ` `    ` `    ` `if` `(!isValid(x, y1, y2)) ` `return` `INT_MIN;` `    ` `    ` `if` `(x == R-1 && y1 == 0 && y2 == C-1)` `       ` `return` `(y1 == y2)? arr[x][y1]: arr[x][y1] + arr[x][y2];` `    ` `    ` `if` `(x == R-1) ` `return` `INT_MIN;` `    ` `    ` `if` `(mem[x][y1][y2] != -1) ` `return` `mem[x][y1][y2];` `    ` `    ` `int` `ans = INT_MIN;` `    ` `    ` `int` `temp = (y1 == y2)? arr[x][y1]: arr[x][y1] + arr[x][y2];` `    ` `       ` `    ` `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);` `}` `int` `geMaxCollection(` `int` `arr[R][C])` `{` `    ` `    ` `int` `mem[R][C][C];` `    ` `memset` `(mem, -1, ` `sizeof` `(mem));` `    ` `    ` `    ` `return` `getMaxUtil(arr, mem, 0, 0, C-1);` `}` `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

 `class` `GFG` `{` `    ` `static` `final` `int` `R = ` `5` `;` `static` `final` `int` `C = ` `4` `;` `static` `boolean` `isValid(` `int` `x, ` `int` `y1, ` `int` `y2)` `{` `    ` `return` `(x >= ` `0` `&& x < R && y1 >=` `0` `&&` `            ` `y1 < C && y2 >=` `0` `&& y2 < C);` `}` `static` `int` `getMaxUtil(` `int` `arr[][], ` `int` `mem[][][],` `                        ` `int` `x, ` `int` `y1, ` `int` `y2)` `{` `    ` `    ` `    ` `if` `(!isValid(x, y1, y2)) ` `return` `Integer.MIN_VALUE;` `    ` `    ` `if` `(x == R-` `1` `&& y1 == ` `0` `&& y2 == C-` `1` `)` `    ` `return` `(y1 == y2)? arr[x][y1]: arr[x][y1] + arr[x][y2];` `    ` `    ` `    ` `if` `(x == R-` `1` `) ` `return` `Integer.MIN_VALUE;` `    ` `    ` `if` `(mem[x][y1][y2] != -` `1` `) ` `return` `mem[x][y1][y2];` `    ` `    ` `int` `ans = Integer.MIN_VALUE;` `    ` `    ` `    ` `int` `temp = (y1 == y2)? arr[x][y1]:` `                ` `arr[x][y1] + arr[x][y2];` `    ` `    ` `    ` `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);` `}` `static` `int` `geMaxCollection(` `int` `arr[][])` `{` `    ` `    ` `    ` `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` `;` `        ` `}` `    ` `}` `    ` `    ` `    ` `return` `getMaxUtil(arr, mem, ` `0` `, ` `0` `, C-` `1` `);` `}` `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));` `    ` `}` `}`

## Python3

 `R` `=` `5` `C` `=` `4` `intmin` `=` `-` `10000000` `intmax` `=` `10000000` `def` `isValid(x,y1,y2):` `    ` `return` `((x >` `=` `0` `and` `x < R ` `and` `y1 >` `=` `0` `            ` `and` `y1 < C ` `and` `y2 >` `=` `0` `and` `y2 < C))` `def` `getMaxUtil(arr,mem,x,y1,y2):` `    ` `    ` `if` `isValid(x, y1, y2)` `=` `=` `False` `:` `        ` `return` `intmin` `        ` `    ` `    ` `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` `x` `=` `=` `R` `-` `1` `:` `        ` `return` `intmin` `        ` `    ` `    ` `if` `mem[x][y1][y2] !` `=` `-` `1` `:` `        ` `return` `mem[x][y1][y2]` `        ` `    ` `    ` `ans` `=` `intmin` `    ` `    ` `temp` `=` `0` `    ` `if` `y1` `=` `=` `y2:` `        ` `temp` `=` `arr[x][y1]` `    ` `else` `:` `        ` `temp` `=` `arr[x][y1]` `+` `arr[x][y2]` `        ` `    ` `    ` `    ` `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` `def` `geMaxCollection(arr):` `    ` `    ` `    ` `    ` `mem` `=` `[[[` `-` `1` `for` `i ` `in` `range` `(C)] ` `for` `i ` `in` `range` `(C)] ` `for` `i ` `in` `range` `(R)]` `    ` `    ` `    ` `    ` `    ` `return` `getMaxUtil(arr, mem, ` `0` `, ` `0` `, C` `-` `1` `)` `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))` `    `

## C#

 `using` `System;` `class` `GFG` `{` `    ` `static` `readonly` `int` `R = 5;` `static` `readonly` `int` `C = 4;` `static` `bool` `isValid(` `int` `x, ` `int` `y1, ` `int` `y2)` `{` `    ` `return` `(x >= 0 && x < R && y1 >=0 &&` `            ` `y1 < C && y2 >=0 && y2 < C);` `}` `static` `int` `getMaxUtil(` `int` `[,]arr, ` `int` `[,,]mem,` `                        ` `int` `x, ` `int` `y1, ` `int` `y2)` `{` `    ` `    ` `    ` `if` `(!isValid(x, y1, y2)) ` `return` `int` `.MinValue;` `    ` `    ` `if` `(x == R-1 && y1 == 0 && y2 == C-1)` `    ` `return` `(y1 == y2)? arr[x, y1]: arr[x, y1] + arr[x, y2];` `    ` `    ` `    ` `if` `(x == R-1) ` `return` `int` `.MinValue;` `    ` `    ` `if` `(mem[x, y1, y2] != -1) ` `return` `mem[x, y1, y2];` `    ` `    ` `int` `ans = ` `int` `.MinValue;` `    ` `    ` `    ` `int` `temp = (y1 == y2)? arr[x, y1]:` `                ` `arr[x, y1] + arr[x, y2];` `    ` `    ` `    ` `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);` `}` `static` `int` `geMaxCollection(` `int` `[,]arr)` `{` `    ` `    ` `    ` `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;` `        ` `}` `    ` `}` `    ` `    ` `    ` `return` `getMaxUtil(arr, mem, 0, 0, C-1);` `}` `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));` `    ` `}` `}`

## Javascript

 ```

var R = 5;

var C = 4;

function isValid(x, y1, y2)

{

return (x >= 0 && x < R && y1 >=0 &&

y1 < C && y2 >=0 && y2 < C);

}

function getMaxUtil(arr, mem,

x, y1, y2)

{

if (!isValid(x, y1, y2)) return Number.MIN_VALUE;

if (x == R-1 && y1 == 0 && y2 == C-1)

return (y1 == y2)? arr[x][y1]: arr[x][y1] + arr[x][y2];

if (x == R-1) return Number.MIN_VALUE;

if (mem[x][y1][y2] != -1) return mem[x][y1][y2];

var ans = Number.MIN_VALUE;

var temp = (y1 == y2)? arr[x][y1]:

arr[x][y1] + arr[x][y2];

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);

}

function geMaxCollection(arr)

{

var mem = Array(R).fill().map(()=>Array(C).fill().map(()=>Array(C).fill(0)));

for(i = 0; i < R; i++)

{

for(j = 0; j < C; j++)

{

for(l = 0; l < C; l++)

mem[i][j][l]=-1;

}

}

return getMaxUtil(arr, mem, 0, 0, C-1);

}

var arr = [[3, 6, 8, 2],

[5, 2, 4, 3],

[1, 1, 20, 10],

[1, 1, 20, 10],

[1, 1, 20, 10],

];

document.write("Maximum collection is " +

geMaxCollection(arr));

```

Output:

`Maximum collection is 73`

Thanks to Gaurav Ahirwar for suggesting above problem and solution.