石子游戏 II

一、题目描述

题目链接:https://leetcode-cn.com/problems/stone-game-ii/

 

二、题目分析

本题参考题解:https://leetcode-cn.com/problems/stone-game-ii/solution/java-dong-tai-gui-hua-qing-xi-yi-dong-17xing-by-lg/

下面写一下自己的一些理解。

首先,由于石子的个数必为整数,若M大于剩余的石子数,那我们一起把它们拿走便是最优的,如果说一次拿不完,那么我们尽量让下一个人少拿。为了确定下一个人少拿,我们应该从后往前推,这样才知道后面的状态。

还有一些要注意的点,不要被题目中“两个人”这一条件束缚,我们若使用dp,我们从后往前推推到最后一个状态就是第一个人的最优解。

 

三、代码

    public int stoneGameII(int[] piles) {
        int len = piles.length;
        // dp[i][j]代表在[i,len-1]的piles中,如果M = j,最大的得分
        int[][] dp = new int[len][len+1];
        // 使用sum记录后缀和,用于计算若不能把剩余的石子全拿完,应该怎么拿让后面的人拿的少
        int sum = 0;
        for (int i = len - 1; i >= 0; i --) {
            sum += piles[i];
            // 这里要注意M是多种可能,虽然题目中的意思M会取决于上一个状态
            // 但是,只要i和M确定,dp的值其实就可以计算了,因为dp的值只和后面的值有关
            // 因此我们应该将M所有可能计算dp,无论接下来前面的dp会不会用到它
            for (int M = 1; M <= len; M ++ ) {
                // 若已经可以全部拿完了
                if (i + 2 * M >= len) {
                    dp[i][M] = sum;
                } else {
                    // 若不能全部拿完
                    for (int x = 1; x <= 2 * M; x ++ ) {
                        dp[i][M] = Math.max(dp[i][M], sum - dp[i+x][Math.max(x,M)]);
                    }
                }
            }
        }
        return dp[0][1];
    }

 

你可能感兴趣的:(石子游戏 II)