题目
A、B两伙马贼意外地在一片沙漠中发现了一处金矿,双方都想独占金矿,但各自的实力都不足以吞下对方,经过谈判后,双方同意用一个公平的方式来处理这片金矿。处理的规则如下:他们把整个金矿分成n段,由A、B开始轮流从最左端或最右端占据一段,直到分完为止。
马贼A想提前知道他们能分到多少金子,因此请你帮忙计算他们最后各自拥有多少金子?(两伙马贼均会采取对己方有利的策略)
思路
- 二维数组
dp[i][j]
表示 A 在 i 和 j 段内所能获得的最大值 - 一维数组
sum[i]
表示 1~i 金矿质量和
动态规划方程为:
dp[i][j] = sum[j] - sum[i-1] + Math.min(dp[i+1][j], dp[i][j-1]);
代码
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.StreamTokenizer; public class Main { static StreamTokenizer streamTokenizer = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); public static void main(String[] args) throws IOException { int T = nextInt(); for (int j = 1; j <= T; j++) { int n = nextInt(); int[] a = new int[n]; for (int i = 0; i < n; i++) { a[i] = nextInt(); } int[] res = solve(a); System.out.printf("Case #%d: %d %d", j, res[0], res[1]); } } static int[] solve(int[] nums) { int len = nums.length; int[] sum = new int[len + 1]; int[][] dp = new int[len + 1][len + 1]; sum[0] = 0; for (int i = 1; i <= len; i++) { dp[i][i] = nums[i - 1]; sum[i] = sum[i - 1] + nums[i - 1]; } for (int i = len - 1; i > 0; i--) { // 从右端开始计算 for (int j = i; j <= len; j++) { dp[i][j] = sum[j] - sum[i - 1] - Math.min(dp[i + 1][j], dp[i][j - 1]); } } return new int[]{dp[1][len], sum[len] - dp[1][len]}; } static int nextInt() throws IOException { streamTokenizer.nextToken(); return (int) streamTokenizer.nval; } static long nextLong() throws IOException { streamTokenizer.nextToken(); return (long) streamTokenizer.nval; } }