LintCode396.硬币排成线Ⅲ

有 n 个硬币排成一条线, 第 i 枚硬币的价值为 values[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
        int n = values.length;
        int[][] dp = new int[n][n];
        boolean[][] flag = new boolean[n][n];

        int sum = 0;
        for (int now : values)
            sum += now;

        return sum < 2 * MemorySearch(0, values.length - 1, dp, flag, values);
    }

    int MemorySearch(int left, int right, int[][] dp, boolean[][] flag, int[] values) {

        if (flag[left][right])
            return dp[left][right];
        flag[left][right] = true;
        if (left > right) {
            dp[left][right] = 0;
        } else if (left == right) {
            dp[left][right] = values[left];
        } else if (left + 1 == right) {
            dp[left][right] = Math.max(values[left], values[right]);
        } else {
            int pick_left = Math.min(MemorySearch(left + 2, right, dp, flag, values),
                    MemorySearch(left + 1, right - 1, dp, flag, values)) + values[left];
            int pick_right = Math.min(MemorySearch(left, right - 2, dp, flag, values),
                    MemorySearch(left + 1, right - 1, dp, flag, values)) + values[right];
            dp[left][right] = Math.max(pick_left, pick_right);
        }
        return dp[left][right];
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值