Leetcode.2017 网格游戏 Rating : 1719
给你一个下标从 0 开始的二维数组 grid
,数组大小为 2 x n
,其中 grid[r][c]
表示矩阵中 (r, c)
位置上的点数。现在有两个机器人正在矩阵上参与一场游戏。
两个机器人初始位置都是 (0, 0)
,目标位置是 (1, n-1)
。每个机器人只会 向右 ((r, c)
到 (r, c + 1)
) 或 向下 ((r, c)
到 (r + 1, c)
) 。
游戏开始,第一个 机器人从 (0, 0)
移动到 (1, n-1)
,并收集路径上单元格的全部点数。对于路径上所有单元格 (r, c)
,途经后 grid[r][c]
会重置为 0 。然后,第二个 机器人从 (0, 0)
移动到 (1, n-1)
,同样收集路径上单元的全部点数。注意,它们的路径可能会存在相交的部分。
第一个 机器人想要打击竞争对手,使 第二个 机器人收集到的点数 最小化 。与此相对,第二个 机器人想要 最大化 自己收集到的点数。两个机器人都发挥出自己的 最佳水平 的前提下,返回 第二个 机器人收集到的 点数 。
输入:grid = [[2,5,4],[1,5,1]]
输出:4
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 0 + 4 + 0 = 4 个点。
输入:grid = [[3,3,1],[8,5,2]]
输出:4
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 3 + 1 + 0 = 4 个点。
输入:grid = [[1,3,1,15],[1,3,3,1]]
输出:7
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 1 + 3 + 3 + 0 = 7 个点。
分析:
红色的是第一个机器人走过的路径。
因为机器人只能 向右 或者 向下 走,所以第二个机器人就只能选择走两段蓝色的路径其中的一段。
所以第二个机器人就选择 两段蓝色路径和最大的那段。第一个机器人就是让这个 较大的蓝色段的路径和最小。
我们定义前缀和 s
:
i
个元素的和i
个元素的和所以我们只需要遍历一次,不断更新答案 ans
,ans = min ( ans , max( s[0][n] - s[0][i] , s[1][i-1] ) )
。
时间复杂度: O(n)O(n)O(n)
C++代码:
using LL = long long;
class Solution {
public:long long gridGame(vector>& grid) {int n = grid[0].size();LL s[2][n+1];memset(s,0,sizeof s);for(int i = 1;i <= n;i++){s[0][i] = s[0][i-1] + grid[0][i-1];s[1][i] = s[1][i-1] + grid[1][i-1];}LL ans = 1e18;for(int i = 1;i <= n;i++){ans = min(ans,max(s[0][n] - s[0][i] , s[1][i-1]) );}return ans;}
};
Java代码:
class Solution {public long gridGame(int[][] grid) {int n = grid[0].length;long[][] s = new long[2][n+1];for(int i = 1;i <= n;i++){s[0][i] = s[0][i-1] + grid[0][i-1];s[1][i] = s[1][i-1] + grid[1][i-1];}long ans = Long.MAX_VALUE;for(int i = 1;i <= n;i++){ans = Math.min(ans,Math.max(s[0][n] - s[0][i] , s[1][i-1]) );}return ans;}
}