lintcode-medium-Coins in a Line II

There are n coins with different value in a line. Two players take turns to take one or two coins from left side until there are no more coins left. The player who take the coins with the most value wins.

Could you please decide the first player will win or lose?

Given values array A = [1,2,2], return true.

Given A = [1,2,4], return false.

 

思路:

动态规划,用一个int数组代表从第i个硬币开始到最后一个,第一个拿的玩家能够拿到的硬币的最大价值。

状态转移:

在i个硬币处,第一个拿的玩家有两个选择:

1. 只拿一个硬币values[i],这时第二个拿的玩家可以选择拿一个或者拿两个,考虑第二个玩家也是理性的,会试图使第一个拿的人得到价值最小,所以dp[i] = values[i] + min(dp[i + 1], dp[i+2])

2. 拿两个硬币value[i] + values[i + 1],第二个玩家同样可以拿一个或者两个,dp[i] = values[i + 1] + values[i + 2] + min(dp[i + 3], dp[i + 4])

所以第一个拿的玩家可以拿到最大价值为dp[0],第二个玩家可以得到总价值减去dp[0],比较这两个值可以得到第一个拿的人是否能赢

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
        
        if(values == null || values.length <= 2)
            return true;
        
        int[] dp = new int[values.length + 1];
        int size = values.length;
        dp[size] = 0;
        dp[size - 1] = values[size - 1];
        dp[size - 2] = values[size - 1] + values[size - 2];
        dp[size - 3] = values[size - 2] + values[size - 3];
        
        for(int i = size - 4; i >= 0; i--){
            int val1 = values[i] + Math.min(dp[i + 2], dp[i + 3]);
            int val2 = values[i] + values[i + 1] + Math.min(dp[i + 3], dp[i + 4]);
            
            dp[i] = Math.max(val1, val2);
        }
        
        int sum = 0;
        for(int i = 0; i < values.length; i++)
            sum += values[i];
        
        return dp[0] > sum - dp[0];
    }
}

 

posted @ 2016-03-16 05:18  哥布林工程师  阅读(174)  评论(0编辑  收藏  举报