题目
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;
}
} 
京公网安备 11010502036488号