395. Coins in a Line II

最后更新

这个题做得也不好,dp[n]尝试写了几下,不太对。

应该是类似于gem theory的题。

当只有1个硬币剩下的时候直接拿走,不BB。
剩俩的时候也都拿了。。

dp[n]表示剩下多少个硬币。

轮到我们拿第i个硬币的时候,有2种情况:

  • 我们拿这个 i 。
    • 对手选择拿1个,就是第i+1个,然后第i+ 2轮到我们,我们再决定。
    • 对手选择拿2个,i+1和i+2, 然后i+3轮到我们。
  • 我们拿这个i,再拿下一个i+1。
    • 对手选择拿1个,就是第i+2, 然后i+3轮到我们。
    • 对手选择拿2个,i+2, i+3,然后i+4该我们选择了。

当前怎么选取决于拿1个得的多还是拿2个得的多:
dp[i] = Math.max(拿1个, 拿2个)

但是注意中间对手拿的时候,他也要选择对他有利的,所以再轮到我们的时候,我们就拿得相对小的那个选择。

拿1个 = 当前的1个硬币 + Math.min(第i+2轮到我们,第i+3轮到我们)
拿2个 = 当前的2个硬币 + Math.min(第i+3轮到我们, 第i+4轮到我们)

思路很绕,是一个极小极大的思路,minimax。
另一个地方是并没有急于计算对手能拿多少而减去他的决定,而是尝试在他的选择下直接获取我们的硬币,最后看看拿的数量过不过半。

一头雾水。。。

public class Solution {

    public boolean firstWillWin(int[] values) {

        if (values.length <= 2) return true;
        
        // max profit when there are n coins left
        int[] dp = new int[values.length + 1];
        
        Arrays.fill(dp, -1);
        
        int total = values.length;
        
        dp[0] = 0;
        // only 1 left, we get that one
        dp[1] = values[total-1];
        // only 2 left, we grab those 2 fucking coins
        dp[2] = values[total-2] + values[total-1];
        
        // wat will we get when there are n left..
        dp[total] = nthProfit(total, dp, values);
        int sum = 0;
        for (int i : values) sum += i;
        return dp[total] > sum/2;
        
    }
    
    public int nthProfit(int leftOver, int[] dp, int[] values) {
        if (leftOver <= 0) return 0;
        if (dp[leftOver] != -1) return dp[leftOver];
        
        int total = values.length;
        
        int pickOne = values[total - leftOver] + 
                   Math.min(nthProfit(leftOver-2, dp, values), 
                       nthProfit(leftOver-3, dp, values));
                       
        int pickTwo = values[total - leftOver] + values[total - leftOver + 1] +
                   Math.min(nthProfit(leftOver-3, dp, values),
                       nthProfit(leftOver-4, dp, values));
        dp[leftOver] = Math.max(pickOne, pickTwo);
        return dp[leftOver];
    }
}

转载于:https://www.cnblogs.com/reboot329/p/6209693.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值