Leetcode_1690_石子游戏 Ⅶ_动态规划

12/17

后有详细解答步骤
class Solution {
    public int stoneGameVII(int[] stones) {
        int n=stones.length;
        //从第一个到第i个,石头的总数
        int []sum=new int[n];
        sum[0]=stones[0];
        for(int i=1;i<n;i++){
            sum[i]=sum[i-1]+stones[i];
        }
        //从第i个到第j个两者最大的差值
        int [][]dp=new int[n][n];
        /*
        dp[x][x]=0;
        dp[x-1][x-1]=0;
        dp[x-1][x]=min(stones[x-1],stones[x]);
        dp[x-2][x]=max(sum[x-1,x]-dp[x-1][x],sum[x-2,x-1]-dp[x-2][x-1]);
        */
        for(int st=n-2;st>=0;st--){
            for(int ed=st+1;ed<n;ed++){
                dp[st][ed]=Math.max(-dp[st+1][ed]+sum[ed]-sum[st],-dp[st][ed-1]+sum[ed-1]-(st==0?0:sum[st-1]));
            }
        }
        return dp[0][n-1];
    }
}

第一步:观察

观察到这题无法用贪心完成,需要用动态规划

第二步:思考转移的状态是什么

我们首先先明确一点,先取的一定比后取的拿的多
最终需要返回的是第0到第n-1个的石子时候,二者的最大差值
我们将其前进一步
很容易发现就两种转换方式
要么取左边,要么取右边

取左边的价值是获得第1到第n-1个石子的总和
代价是减少(从1到第n-1个石子时,二者的最大差值)

取右边的价值是获得第0到第n-2个石子的总和
取右边的代价是减少(从第0到第n-2个石子时,二者的最大差值)

写成公式就是
dp[0][n-1]=max(sum[1,n-1]-dp[1][n-1],sum[0,n-2]-dp[0][n-2]);

第三步:思考转移的顺序

很容易发现我们的公式是从外向内转移的
也就是我们为了获取最终dp[0,n-1],
我们必须先获取内部的dp[1][n-1]与dp[0][n-2],
也就是我们的转移顺序是从内而外
即先算出内部,再慢慢向外部转移
我们观察到
当起始点和终止点重合时:dp[x][x]=0;
而当起始点和终止点相差为1时,dp[x-1][x]=min(stones[x-1],stones[x]);
仍满足转移方程,并且dp[x][x]的值为int数组初值,我们不必提前赋值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值