本题出自力扣题库第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]
题解:
本题是个典型的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];
}
}