司马算法(2020.02.14)

动态规划

	/**
	 * 有一排正数,玩家A和玩家B都可以看到。
	 * 每位玩家在拿走数字的时候,都只能从最左和最右的数中选择一个。
	 * 玩家A先拿,玩家B再拿,两人交替拿走所有的数字,
	 * 两人都力争自己拿到的数的总和比对方多。请返回最后获胜者的分数。
	 * 例如:
	 * 5,2,3,4
	 * 玩家A先拿,当前他只能拿走5或者4。
	 * 如果玩家A拿走5,那么剩下2,3,4。轮到玩家B,此时玩家B可以选择2或4中的一个,…
	 * 如果玩家A拿走4,那么剩下5,2,3。轮到玩家B,此时玩家B可以选择5或3中的一个,…
	 * @param arr[] 数组 i数组第一个 j数组第二个
	 */

解题思路

http://www.asdasdasd.top/1-03.png

Coding

package com.cy.work01;

public class Mycode {

    /**
     * 暴力算法 --> 动态规划
     *
     * @param arr
     * @return
     */
    public static int my_way(int[] arr) {
        //如果数组为空 直接返回
        if (arr == null || arr.length == 0) {
            return 0;
        }
        //如果数组不为空 则计算出总分 总分用来比较先行者的分数和后行者的分数
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        //计算先发者的分数 启动先行者拿的分数是从数组两侧第一个进行拿取 i,j表示数组两侧的下标
        int first_point = first(arr, 0, arr.length - 1);
        return Math.max(sum - first_point, first_point);
    }

    private static int first(int[] arr, int i, int j) {
        //判断数组的长度
        if (i == j) {
            return arr[i];
        }
        if (i + 1 == j) {
            return Math.max(arr[i], arr[j]);
        }

        return Math.max(
                //当先行者取最左边的数时 i为最左边 则下次拿到肯定是最小的 
                arr[i] + Math.min(first(arr, i + 2, j), first(arr, i + 1, j - 1)),
                //所以拿到的小值的那个也为先发者拿到的
                arr[j] + Math.min(first(arr, i + 1, j - 1), first(arr, i, j - 2))
                );
    }
}
发布了19 篇原创文章 · 获赞 6 · 访问量 1981

猜你喜欢

转载自blog.csdn.net/qq_42252844/article/details/104317847