题目链接
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)
,同样收集路径上单元的全部点数。注意,它们的路径可能会存在相交的部分。
第一个 机器人想要打击竞争对手,使 第二个 机器人收集到的点数 最小化 。与此相对,第二个 机器人想要 最大化 自己收集到的点数。两个机器人都发挥出自己的 最佳水平 的前提下,返回 第二个 机器人收集到的 点数 。
示例 1:
输入:grid = [[2,5,4],[1,5,1]]
输出:4
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 0 + 4 + 0 = 4 个点。
示例 2:
输入:grid = [[3,3,1],[8,5,2]]
输出:4
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 3 + 1 + 0 = 4 个点。
示例 3:
输入:grid = [[1,3,1,15],[1,3,3,1]]
输出:7
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 1 + 3 + 3 + 0 = 7 个点。
提示:
- g r i d . l e n g t h = = 2 grid.length == 2 grid.length==2
- n = = g r i d [ r ] . l e n g t h n == grid[r].length n==grid[r].length
- 1 < = n < = 5 ∗ 1 0 4 1 <= n <= 5 * 10^4 1<=n<=5∗104
- 1 < = g r i d [ r ] [ c ] < = 1 0 5 1 <= grid[r][c] <= 10^5 1<=grid[r][c]<=105
分析:
红色的是第一个机器人走过的路径。
因为机器人只能 向右 或者 向下 走,所以第二个机器人就只能选择走两段蓝色的路径其中的一段。
所以第二个机器人就选择 两段蓝色路径和最大的那段。第一个机器人就是让这个 较大的蓝色段的路径和最小。
我们定义前缀和 s
:
-
s
(
0
,
i
)
s(0,i)
s(0,i)代表第一行,前
i
个元素的和 -
s
(
1
,
i
)
s(1,i)
s(1,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<vector<int>>& 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;
}
}