lintcode :Coins in Line II 硬幣排成線 II


題目

有 n 個不同價值的硬幣排成一條線。兩個參賽者輪流從左邊依次拿走 1 或 2 個硬幣,直到沒有硬幣為止。計算兩個人分別拿到的硬幣總價值,價值高的人獲勝。

請判定 第一個玩家 是輸還是贏?

樣例

給定數組 A = [1,2,2], 返回 true.

給定數組 A = [1,2,4], 返回 false.

解題

動態規划、博弈論

坑死,看了好久

定義dp[i]表示從i到end能取到的最大值

當我們在i處,有兩種選擇:

1.若取values[i],對方可以取values[i+1] 或者values[i+1] + values[i+2]

當對方取values[i+1] 后 ,我們只能從 i+2 到end內取,我們所取得最大值是dp[i+2],  注意:對方所選取的結果一定是使得我們以后選取的值最小

當對方取values[i+1] + values[i+2]后,我們只能從i+3到end內取,我們所取得最大值是dp[i+3]。

此時:dp[i] = values[i] + min(dp[i+2],dp[i+3]) , 注意:對方所選取的結果一定是使得我們以后選取的值最小

2.若取values[i] + values[i+1],對方可取values[i+2] 或者values[i+2] + values[i+3]

當對方取values[i+2]后,我們只能從i+3到end內取,我們取得最大值是dp[i+3]

當對方取values[i+2]+values[i+3]后,我們只能從i+4到end內去,我們取得最大值是dp[i+4]

此時:dp[i] = values[i] + values[i+1]+min(dp[i+3],dp[i+4])

這里的取最小值和上面一樣的意思,對方選取過之后的值一定是使得我們選取的值最小,對方不傻並且還很聰明

最后我們可以取上面兩個dp[i]的最大值,就是答案,這里意思是:對方留得差的方案中,我們選取的最大值。

參考鏈接 

public class Solution {
    /**
     * @param values: an array of integers
     * @return: a boolean which equals to true if the first player will win
     */
    public boolean firstWillWin(int[] values) {
        // write your code here
        // dp 表示從i到end 的最大值
        // int values[] ={1,2,4,3,4,8,5,6,12};
        int len = values.length;
        // 長度小於2的時候第一個人一定獲勝
        if(len <= 2)
            return true;
        int dp[] = new int[len+1];
        dp[len] = 0;
        dp[len-1] = values[len-1];
        dp[len-2] = values[len-1] + values[len - 2];
        dp[len - 3] = values[len-3] + values[len - 2];
        for(int i = len -4;i>=0;i--){
            dp[i] = values[i] + Math.min(dp[i+2],dp[i+3]);
            dp[i] = Math.max(dp[i],values[i]+values[i+1]+ Math.min(dp[i+3],dp[i+4]));

        }
        int sum = 0;
        for(int a:values)
            sum +=a;
        return dp[0] > sum - dp[0];
    }
}
Java Code

總耗時: 1114 ms

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM