试题 算法训练 逗志芃的危机 (Java实现 通俗易懂)
问题描述: 逗志芃又一次面临了危机。逗志芃的妹子是个聪明绝顶的人,相比之下逗志芃就很菜了。现在她妹子要和他玩一个游戏,这个游戏是这样的:一共有n个数(n是偶数)写成一行,然后两个人轮流取数,每次只能从最前面或者最后面取走一个数,全部取完则游戏结束,之后每个人取走的数的和就是每个人的得分。由于逗志芃妹子很厉害,但他又不想输,所以只能找到你了,你要告诉他最多可以得到多少分。(注意,妹子智商是maxlongint所以是不会犯错的,每次的策略必然最优,而且逗志芃是先手) 输入格式 第一行一个数n,表示有n个数。 第二行就是进行游戏的n个数。 输出格式 一个数,最高得分 样例输入 2 10 20
样例输出 20
数据规模和约定 例:0<n,m<=1000,每个数不超过10000 。
思路: 本题跟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)); } } }
下一篇:
平衡二叉树AVL、哈夫曼树