Dynamic Programming学习笔记 (44) - 球会落何处 (力扣# 1706)

159 阅读2分钟

本题出自力扣题库第1706题。题面大意如下:

用一个大小为m x n的二维网格grid表示一个箱子。你有n颗球。箱子的顶部和底部都是开着的。 箱子中的每个单元格都有一个对角线挡板,跨过单元格的两个角,可以将球导向左侧或者右侧。 将球导向右侧的挡板跨过左上角和右下角,在网格中用 1 表示。 将球导向左侧的挡板跨过右上角和左下角,在网格中用 -1 表示。 在箱子每一列的顶端各放一颗球。每颗球都可能卡在箱子里或从底部掉出来。如果球恰好卡在两块挡板之间的 "V"形图案,或者被一块挡导向到箱子的任意一侧边上,就会卡住。 返回一个大小为n的数组 answer ,其中 answer[i] 是球放在顶部的第i列后从底部掉出来的那一列对应的下标,如果球卡在盒子里,则返回 -1 。

示例:

输入:grid = [[1,1,1,-1,-1],[1,1,1,-1,-1],[-1,-1,-1,1,1],[1,1,1,1,-1],[-1,-1,-1,-1,-1]]
输出:[1,-1,-1,-1,-1]

ball.jpg

题解:

本题是个典型的DP应用,其基本思路在于根据球当前的行,列位置以及网格数值,使用题目给出的规则来计算其下一个位置,一直到球被挡住或从底部掉出为止。

Java代码如下:

class Solution {
    public int[] findBall(int[][] grid) {
        int M = grid.length;
        int N = grid[0].length;

        if (N == 1) {
            return new int[]{-1};
        }

        int[][] dp = new int[M + 1][N];

        for (int col = 0; col < N; col ++) {
            dp[M][col] = col;
        }

        for (int row = M - 1; row >= 0; row --) {
            if (row == 0) {
                row = 0;
            }
            if (grid[row][0] == -1) {
                dp[row][0] = -1;
            } else if (grid[row][0] == 1 && grid[row][1] == -1) {
                dp[row][0] = -1;
            } else {
                dp[row][0] = dp[row + 1][1];
            }

            if (grid[row][N - 1] == 1) {
                dp[row][N - 1] = -1;
            } else if (grid[row][N - 1] == -1 && grid[row][N - 2] == 1) {
                dp[row][N - 1] = -1;
            } else {
                dp[row][N - 1] = dp[row + 1][N - 2];
            }

            for (int col = 1; col < N  - 1; col ++) {
                if (grid[row][col] == 1 && grid[row][col + 1] == -1) {
                    dp[row][col] = -1;
                } else if (grid[row][col] == -1 && grid[row][col - 1] == 1) {
                    dp[row][col] = -1;
                } else {
                    dp[row][col] = dp[row + 1][col + grid[row][col]] ;
                }
            }
        }

        return dp[0];
    }
}