两个人轮流从一个序列取数,每次只能从两端取走一个数

题目大意:
两个人轮流从一个序列取数,每次只能从两端取走一个数。每个人都采用最优策略,问两人最终所能取到的分数之和分别是多少?

输入
4 7 2 9 5 2
输出
18 11

递归方法

public class Main {
    public static void main(String[] args) throws Exception {
        int[] arr = {4, 7, 2, 9, 5, 2};//18 11
        //需要一个函数得到剩余自己能获得的最大值
        System.out.println(more(arr, 0, arr.length - 1));
    }

    public static int more(int[] arr, int s, int e) {//该函数希望自己得到的最多
        if(arr==null||arr.length==0)return 0;
        if (e - s == 0) return arr[s];//最后一个元素是自己拿
        return Math.max(arr[s] + less(arr, s + 1, e), arr[e] + less(arr, s, e - 1));
    }

    public static int less(int[] arr, int s, int e) {//该函数希望对方得到的最少,返回的是对方能得到的值
        if (e - s == 0) return 0;
        return Math.min(more(arr, s + 1, e), more(arr, s, e - 1));
    }
}

动态规划
https://www.nowcoder.com/questionTerminal/60bed226b2364b628c98ffe24ca4aa09
别人写的我暂时理解不了

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        System.out.println(Arrays.toString(new Main().findMaxScore(new int[]{4, 7, 2, 9, 5, 2})));
    }

    public int[] findMaxScore(int[] nums) {
//要使用动态规划  
        int len = nums.length;
        int[][] dp = new int[2][len]; // 一行记录一个人的得分,最后再判断哪个分数是哪个人的
        dp[0] = Arrays.copyOf(nums, len);
        int a = 0;
        int b = 1;
        for (int i = 1; i < len; i++) {// i+1表示当前还剩几个数,倒着推到整个数组
// 交换ab的值;  
            a = a ^ b;
            b = a ^ b;
            a = a ^ b;
            for (int j = 0; j < len - i; j++) {
                dp[b][j] = nums[j] + dp[a][j + 1] > nums[j + i] + dp[a][j] ? dp[b][j + 1] : dp[b][j];
                dp[a][j] = Math.max(nums[j] + dp[a][j + 1], nums[j + i] + dp[a][j]);
            }
        }
//System.out.println(Arrays.toString(dp[0]));  
//System.out.println(Arrays.toString(dp[1]));  
// System.out.println("------------------");  } 
//后拿那个人得分为dp[0][0], 先拿那个人得分为dp[1][0];  
        return len % 2 == 0 ? new int[]{dp[1][0], dp[0][0]} : new int[]{dp[0][0], dp[1][0]};
    }
}

你可能感兴趣的:(动态规划)