leetcode 1140. Stone Game II 的解法(动态规划标准例题)

本文探讨了一款石子游戏的最佳策略,通过动态规划算法,寻找亚历克斯在与李的游戏中能获得的最大石子数量。介绍了动态规划的二维数组实现,以及递归公式,最终实现了高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目是:

亚历克斯和李继续他们的石子游戏。许多堆石子 排成一行,每堆都有正整数颗石子 piles[i]。游戏以谁手中的石子最多来决出胜负。
亚历克斯和李轮流进行,亚历克斯先开始。最初,M = 1。
在每个玩家的回合中,该玩家可以拿走剩下的 前 X 堆的所有石子,其中 1 <= X <= 2M。然后,令 M = max(M, X)。
游戏一直持续到所有石子都被拿走。
假设亚历克斯和李都发挥出最佳水平,返回亚历克斯可以得到的最大数量的石头。

粗略思路:

(1)求最大值,采用动态规划可减少重复计算;

(2)亚历克斯和李均表现为最佳水平,即采用同一策略进行游戏,所以动态规划数组唯一。

详细思路:

(1)选取结果受M和当前的坐标i 影响,所以是动态规划的数据是二维数组;

(2)剩下的石头如果小于2M,可以把剩下的所有石头拿走,可作为动态规划的起始条件;

(3)当前可取的石子为,剩下的所有石头 - 上一次取走的石头,求当前可取石头的最大值,所以递归式为

          

dp[i][j]=max(dp[i][j],resum[i]-dp[i+x][max(j,x)]);

其中resum[i]为剩下的所有石头,上一次取走的石头dp[i+x][max(j,x)],x为这次取的石头堆数,max(j,x)即M = max(M, X)。

代码如下:

class Solution {
public:
    int stoneGameII(vector<int>& piles) {
        int n=piles.size();
        //设置二维动态规划数组,分别式当前回合的起始坐标和M
        vector<vector<int>> dp(n,vector<int>(n,0));
        //求剩下的所有石头总和
        vector<int> resum(n,0);
        int sum=0;
        for(int i=n-1;i>=0;i--)
        {
            sum+=piles[i];
            resum[i]=sum;
        }
        //初始化动态规划初始条件,剩下的石头如果小于2M,可以把剩下的所有石头拿走
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i+2*j>=n)
                {
                    dp[i][j]=resum[i];
                }
            }
        }
        //递归
        for(int i=n-1;i>=0;i--)
        {
            for(int j=n-1;j>=0;j--)
            {
                for(int x=1;x<=2*j && i+x<n;x++)
                    dp[i][j]=max(dp[i][j],resum[i]-dp[i+x][max(j,x)]);
            }
        }
        //返回起始坐标为0,M为1时,亚历克斯可以得到的最大数量的石头
        return dp[0][1];
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值