试题 算法训练 逗志芃的危机 (Java实现 通俗易懂)

问题描述:
  逗志芃又一次面临了危机。逗志芃的妹子是个聪明绝顶的人,相比之下逗志芃就很菜了。现在她妹子要和他玩一个游戏,这个游戏是这样的:一共有n个数(n是偶数)写成一行,然后两个人轮流取数,每次只能从最前面或者最后面取走一个数,全部取完则游戏结束,之后每个人取走的数的和就是每个人的得分。由于逗志芃妹子很厉害,但他又不想输,所以只能找到你了,你要告诉他最多可以得到多少分。(注意,妹子智商是maxlongint所以是不会犯错的,每次的策略必然最优,而且逗志芃是先手)
  
输入格式
  第一行一个数n,表示有n个数。
  第二行就是进行游戏的n个数。
  
输出格式
  一个数,最高得分
  
样例输入
2
10 20

样例输出
20

数据规模和约定
  例:0

思路:
本题跟0-1背包很相似,0-1背包的每一次时取或者不取,而本题的每一次取最前面或者最后面的数字。逗志芃取的时候,选择能取得更多的情况,妹妹取的时候,会让他选择取得更少的情况。用step控制取的轮次,step为单数时,轮到逗志芃,为双数时,妹妹取。

完整代码:

import java.util.Scanner;
public class Main {
    static int[] nums;
    static int[][] res = new int[1000][1000];   // res[i][j]表示i到j区间能取到的最大值
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.nextLine();      //  当第一行为数字,第二行为字符串时,要用sc.nextLine来消除回车带来的影响
        String str = sc.nextLine(); //  获取第二行的字符
        String[] temp = str.trim().split(" ");
        nums = new int[n];
        for (int i=0;i<n;i++){
            nums[i] = Integer.parseInt(temp[i]);
        }
        System.out.println(solve(0,n-1,1));
    }
    /**
     * @param start 前面的指针
     * @param end   后面的指针
     * @param step  表示进行到第几步了
     * @return
     */
    private static int solve(int start, int end, int step){
        if (res[start][end]!=0)     //  当res[i][j]存在时,直接返回    剪枝,避免超时
            return res[start][end];
        if (start==end)     //  当只有一个数时,一定是妹妹取,返回0
            return 0;
        if (step%2==1){ //  步数为奇数时,逗志凡取,返回后面能取得较多的情况
            return res[start][end] = Math.max((nums[start]+solve(start+1,end,step+1)),
                    nums[end]+solve(start,end-1,step+1));
        }else { //  步数为偶数时,妹妹取,返回后面能取得较少的情况
            return res[start][end] = Math.min(solve(start+1,end,step+1),
                    solve(start,end-1,step+1));
        }
    }
}

你可能感兴趣的:(蓝桥杯算法训练,java,算法,蓝桥杯)