【中等】排成一条线的纸牌博弈问题-Java:动态规划解法

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程

package live.every.day.ProgrammingDesign.CodingInterviewGuide.RecursionAndDynamicPrograming;

/**
 * 排成一条线的纸牌博弈问题
 *
 * 【题目】
 * 给定一个整型数组arr,代表数值不同的纸牌排成一条线。玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿,但是每个玩
 * 家每次只能拿走最左或最右的纸牌,玩家A和玩家B都绝顶聪明。请返回最后获胜者的分数。
 *
 * 【难度】
 * 中等
 *
 * 【解答】
 * 暴力递归的方法中,递归函数一共会有N层,并且是f和s交替出现的。f(i,j)会有s(i+1,j)和s(i,j-1)两个递归分支,s(i,j)也
 * 会有f(i+1,j)和f(i,j-1)两个递归分支。所以整体的时间复杂度为O(2^N),额外空间复杂度为O(N)。下面介绍动态规划的方法,
 * 如果arr长度为N,生成两个大小为NxN的矩阵f和s,f[i][j]表示函数f(i,j)的返回值,s[i][j]表示函数s(i,j)的返回值。规定
 * 一下两个矩阵的计算方向即可。
 * 具体过程请参看如下代码中的win2方法。
 * 如下的win2方法中,矩阵f和s一共有O(N^2)个位置,每个位置计算的过程都是O(1)的比较过程,所以win2方法的时间复杂度为
 * O(N^2),额外空间复杂度为O(N^2)。
 *
 * @author Created by LiveEveryDay
 */
public class LineUpPoker2 {

    public static int win2(int[] arr) {
        if (arr == null || arr.length == 0) {
            return 0;
        }
        int[][] f = new int[arr.length][arr.length];
        int[][] s = new int[arr.length][arr.length];
        for (int j = 0; j < arr.length; j++) {
            f[j][j] = arr[j];
            for (int i = j - 1; i >= 0; i--) {
                f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]);
                s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]);
            }
        }
        return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]);
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 100, 4};
        System.out.printf("The score is: %d", win2(arr));
    }

}

// ------ Output ------
/*
The score is: 101
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值