美文网首页
leetcode 877 石子游戏

leetcode 877 石子游戏

作者: jeneen1129 | 来源:发表于2021-06-16 14:32 被阅读0次

    游戏描述:
    总共偶数堆个石子堆piles[],其中第 i 个石子堆有 piles[i],Alex 和 李 两个玩家参与,每次只能从 数组的头部或者尾部拿取石子堆, 这些石子数总和为奇数 -> 肯定有输赢之分,alex 先拿, 假设两个人都是最佳策略,那么谁会赢?
    alex 赢返回 true,李 赢返回 false

    游戏示例:

    input: [5, 3, 4, 5]
    output: true
    description: 
    亚历克斯先开始,只能拿前 5 颗或后 5 颗石子 。
    假设他取了前 5 颗,这一行就变成了 [3,4,5] 。
    如果李拿走前 3 颗,那么剩下的是 [4,5],亚历克斯拿走后 5 颗赢得 10 分。
    如果李拿走后 5 颗,那么剩下的是 [3,4],亚历克斯拿走后 4 颗赢得 9 分。
    这表明,取前 5 颗石子对亚历克斯来说是一个胜利的举动,所以我们返回 true 。
    

    解法一: 动态规划
    最佳路径类问题的感觉。
    分析如下:
    如果只剩下一堆石子,就只能取走当前的石子;如果剩下>1堆石子,那么就要从头部或者尾部取走石子,然后另一个玩家取走石子。-> 递归。以 alex 和 李 的 石子数量之差,如果最后总数 > 0 则 alex 赢,反之李赢。
    二维数组 dp,行数和列数都为石子的堆数,dp[i][j] 代表 当剩下的石子堆为下标 i - j 时,两个玩家石子数之差的最大值,注意当前玩家不一定是先手 Alex。
    其中 i <= j 时,剩下的石子堆才有意义,因此当 i > j 时,dp[i][j] = 0
    当 i = j 时,只剩下一堆石子,当玩家只能取走这堆石子,因此对于所有 0 <= i < nums.length,都有 dp[i][j] = dp[i][i] = piles[i]
    当 i < j 时,玩家可以选择取走 piles[i] 或者 piles[j],在两种方案中,玩家可以选择 dp[i][j] = max(piles[i] - dp[i+1][j], piles[j] - dp[i][j - 1])

    最后判断 dp[0][piles.length - 1] 的值。

    var stoneGame = function(piles) {
        const length = piles.length;
        const dp = new Array(length).fill(0).map(() => new Array(length).fill(0));
        for (let i = 0; i < length; i++) {
            dp[i][i] = piles[i];
        }
        for (let i = length - 2; i >= 0; i--) {
            for (let j = i + 1; j < length; j++) {
                dp[i][j] = Math.max(piles[i] - dp[i + 1][j], piles[j] - dp[i][j - 1]);
            }
        }
        return dp[0][length - 1] > 0;
    };
    

    优化

    var stoneGame = function(piles) {
        const length = piles.length;
        const dp = new Array(length).fill(0);
        for (let i = 0; i < length; i++) {
            dp[i] = piles[i];
        }
        for (let i = length - 2; i >= 0; i--) {
            for (let j = i + 1; j < length; j++) {
                dp[j] = Math.max(piles[i] - dp[j], piles[j] - dp[j - 1]);
            }
        }
        return dp[length - 1] > 0;
    };
    

    解法二:数学(脑筋急转弯??)
    不管谁是先手,总有人会赢,那么赢的策略(组成堆)肯定是可以确定出来,并且两个玩家都是最佳策略,那么先手只要总是选择数量更多的一组石子就可以总赢。
    其中 alex 是先手,那么返回 true

    var stoneGame = function(piles) {
        return true;
    };
    

    加油!!!!

    相关文章

      网友评论

          本文标题:leetcode 877 石子游戏

          本文链接:https://www.haomeiwen.com/subject/linxyltx.html