1140. Stone Game II (DP, DFS)

The DFS solution is quite intuitive and more like an implementation.

Try to think in this way, every time you can either choose X piles, and this X would affect the latter decisions. And as both Alice and Bobs would make decisions optimally. We need to relate these two variables. The difference between the stones of Alice and Bob gotten is the best way to relate them. That's because if we maximize the difference between Alice and Bob, it is the same to help them maximize the stones.

However, the answer required to return Alice's stones. Let's say Alice's stones are a and Bob's stones are b, the difference is a - b and the total stone of the piles is a + b, total - difference = 2a, thus if we want to get the number of Alice's stones. Just need to use the sum of piles of stone to deduct the difference and then divide it by 2. 

What are the base cases? 

If 2 * m is larger than the rest length of the piles, the optimal choice is to take all of them.

For pruning, we would use a memorization array to store the value of different choices, if there are repeating cases, just return the answer. 

class Solution {
public:
    int dfs(vector<int>& piles, int len, int m, vector<vector<int>> &dp){
        if(len >= piles.size())return 0;
        m = min(int(piles.size()), m);
        if(dp[len][m] > 0)return dp[len][m];
        if(piles.size() <= len + m * 2)return dp[len][m] = accumulate(piles.begin() + len, piles.end(), 0);
        int count = 0;
        int best = INT_MIN;
        for(int i = 1; i <= 2 * m; i++){
            count += piles[len + i - 1];
            int n = dfs(piles, len + i, max(i, m), dp);
            best = max(best, count - n);
        }
        return dp[len][m] = best;
        
    }
        
    int stoneGameII(vector<int>& piles) {
        vector<vector<int>> dp(102, vector<int>(102));
        int part = dfs(piles, 0, 1, dp);
        return (accumulate(piles.begin(), piles.end(), 0) + part)/2;

    }
};

For the Dp solution, it is quite hard to think of. We need to think backwardly. In DFS, we try to use recursion to get the base case answer and then accumulate it backwardly. 

As DP is iterative, we need to do our DP reversely.  

Dp[i][j] is the maximum stone that a player can get starting with index i and with j's taken. 

So the equation of the DP would be to total stones deduct opponents value. dp[i][j] = max(total stone form piles i to n  - dp[i + x][x]))

so it would be an O(n^2 M) solution. 

O(n) for iterating the piles from the back to front,

        O(n) for setting different M,

                O(M) for search for the best M. 

class Solution {
public:
        
    int stoneGameII(vector<int>& piles) {
        vector<vector<int>> dp(102, vector<int>(102));
        int n = piles.size();
        int suffix[102] = {0};
        for(int i = n - 1; i >= 0; i--){
            suffix[i] = suffix[i + 1] + piles[i];
        }
        for (int i = 0; i <= n; i++) {
            dp[i][n] = suffix[i];
        }
        for(int i = n - 1; i >= 0; i--){
            for(int j = 1; j <= n - 1; j++){
                for(int x = 1; x <= 2 * j && i + x <= n; x++){
                    dp[i][j] = max(dp[i][j], suffix[i] - dp[i + x][max(j, x)]);
                }
            }
        }
        return dp[0][1];

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值