前端算法第一八一弹-网格游戏

148 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情

给你一个下标从 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:

图片.png

输入:grid = [[2,5,4],[1,5,1]]
输出:4
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 0 + 4 + 0 = 4 个点。

示例 2:

图片.png

输入:grid = [[3,3,1],[8,5,2]]
输出:4
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。 
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 3 + 1 + 0 = 4 个点。

示例 3:

图片.png

输入:grid = [[1,3,1,15],[1,3,3,1]]
输出:7
解释:第一个机器人的最佳路径如红色所示,第二个机器人的最佳路径如蓝色所示。
第一个机器人访问过的单元格将会重置为 0 。
第二个机器人将会收集到 0 + 1 + 3 + 3 + 0 = 7 个点。

枚举(TLE)

题目中有两个重要信息:

  • grid 是一个 2 * n 的网格
  • 机器人只能 向右 或者 向下 移动

综合一下这两个信息,在一个 2 * 4 的网格中,机器人的移动路径可以枚举为以下 4 种情况(用 x 来表示移动路径):

xooo
xxxx
xxoo
oxxx
xxxo
ooxx
xxxx
ooox

概括地说,机器人可以从 row1 的第 i 个格子向下进入 row2,所以一共有 n 种可能的路径,n 为每行的格子数。我们需要枚举机器人1的 n 种情况中,机器人2能收集的点数的最小值。

在每次枚举中,当机器人1选择从 row1 的第 i 个格子下行到 row2 后,机器人2想要收集点数的话,还剩下两条路径可以选择:

  1. 走 row1,可以收集第一行 (i, n) 这个区间的格子的点数。
  2. 走 row2,可以收集第二行 [0, i) 这个区间的格子的点数。

因为机器人2需要最大化收集的点数,所以取这两种选择中的最大值。

/**
 * @param {number[][]} grid
 * @return {number}
 */
var gridGame = function(grid) {

    let up = grid[0].reduce((prev,cur) => prev + cur),
        result = Infinity,
        d = 0;
    
    for(let i=0;i<grid[0].length;i++){
        up = i == grid[0].length - 1 ? 0 : up -  grid[0][i];
        d = i == 0 ?  0 : d + grid[1][i-1];
        const m = Math.max(up,d);
       result = result <  m ? result : m;
    }
    return result;
    
    
};