Maximum Score From Grid Operations

Hard
Watch on YouTube ↗

Solution

class Solution {
    long pref[][];
    int grid[][];
    int n;
    long dp[][][]; 
    public long maximumScore(int[][] grid) {
        this.grid = grid;
        n = grid.length;

        pref = new long[n+1][n+1];
        dp = new long[2][n+1][n+1];

        for(int j=0; j<n; j++) {
            for(int i=1; i<=n; i++) {
                pref[i][j+1] = pref[i-1][j+1] + grid[i-1][j];
            }
        }

        for(int i=0; i<2; i++) {
            for(int j=0; j<=n; j++) 
                Arrays.fill(dp[i][j], -1);
        }

        return helper(0,0,1);
    }

    long helper(int prevTaken, int prevLen, int col) {
        // O(n^3)
        if(col==n+1)
            return 0;
        if(dp[prevTaken][prevLen][col]!=-1)
            return dp[prevTaken][prevLen][col];

        long ans = 0;
        
        for(int len=0; len<=n; len++) {
            long prevans = 0, currans = 0;

            if(prevTaken==0 && col>1 && len > prevLen) {
                prevans = pref[len][col-1] - pref[prevLen][col-1];
            }

            // currans
            if(prevLen > len) {
                currans = pref[prevLen][col] - pref[len][col];
            }

            long ans1 = currans + prevans + helper(1, len, col+1);
            long ans2 = prevans + helper(0, len, col+1);

            ans = Math.max(ans, Math.max(ans1, ans2));
        }

        return dp[prevTaken][prevLen][col] = ans;
    }
}