分金子(奇虎360 2017春招真题)
题目详情:http://exercise.acmcoder.com/online/online_judge_ques?ques_id=3863&konwledgeId=42
题目描述 :
A、B两伙马贼意外地在一片沙漠中发现了一处金矿,双方都想独占金矿,但各自的实力都不足以吞下对方,经过谈判后,双方同意用一个公平的方式来处理这片金矿。处理的规则如下:他们把整个金矿分成n段,由A、B开始轮流从最左端或最右端占据一段,直到分完为止。
马贼A想提前知道他们能分到多少金子,因此请你帮忙计算他们最后各自拥有多少金子?(两伙马贼均会采取对己方有利的策略)
该题目的解决需要使用动态规划,以下对动态规划做简单介绍:
动态规划的主要难点在于理论上的设计,也就是下面4个步骤的确定:
(1)划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。
(2)确定状态和状态变量:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
(3)确定决策并写出状态转移方程:因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。
(4)寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。
一旦设计完成,实现部分就会非常简单。
使用动态规划求解问题,最重要的就是确定动态规划三要素:
(1)问题的阶段 (2)每个阶段的状态
(3)从前一个阶段转化到后一个阶段之间的递推关系。
递推关系必须是从次小的问题开始到较大的问题之间的转化,从这个角度来说,动态规划往往可以用递归程序来实现,不过因为递推可以充分利用前面保存的子问题的解来减少重复计算,所以对于大规模问题来说,有递归不可比拟的优势,这也是动态规划算法的核心之处。
确定了动态规划的这三要素,整个求解过程就可以用一个最优决策表来描述,最优决策表是一个二维表,其中行表示决策的阶段,列表示问题状态,表格需要填写的数据一般对应此问题的在某个阶段某个状态下的最优值(如最短路径,最长公共子序列,最大价值等),填表的过程就是根据递推关系,从1行1列开始,以行或者列优先的顺序,依次填写表格,最后根据整个表格的数据通过简单的取舍或者运算求得问题的最优解。
f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}
代码和分析如下:
一般情况下,最优决策表中填充的数据是从单一(把AB看作同一个人)角度考虑此问题的最优值,即每一次都是同一个人去选择金矿时的最优值;而实际上在本题目中是A和B交叉去选择,且在选择最优值时,A和B的策略是一样的,所以计算A在某一子问题中的最优值时要相应地减去B在同一子问题中选择的最优值
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int arrayNum = in.nextInt();
for (int i = 1; i <= arrayNum; i++) {
int n = in.nextInt();
int[] a = new int[n+1];
int[] sum = new int[n+1];
sum[0]=0;
for (int j = 1; j < a.length; j++) {
a[j] = in.nextInt();
sum[j] = sum[j-1]+a[j];
}
int maxGold[][] = new int[n+2][n+2];
for (int j = 0; j < n; j++) {
for (int k = 1; k <= n-j; k++) {
maxGold[k][j+k] = Math.max(a[k+j]+sum[k+j-1]-sum[k-1]-maxGold[k][j+k-1],a[k]+sum[k+j]-sum[k]-maxGold[k+1][j+k]);
}
}
System.out.println("Case #" + i + ": " + maxGold[1][n] + " " + (sum[n] - maxGold[1][n]));
}
}
}
样例n=10金子矿段情况140 649 340 982 105 86 56 610 340 879的解题过程:
maxGold[k][k+j] | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
0 |
| B四阶子问题 | A四阶子问题 | B三阶子问题 | A三阶子问题 | B二阶子问题 | A二阶子问题 | B一阶子问题 | A一阶子问题 | B的初始问题 | A的初始问题 |
|
1 | 0 | 140 | 649 | 480 | 1631 | 585 | 1717 | 641 | 2327 | 981 | 3206 | 0 |
2 |
| 0 | 649 | 649 | 1322 | 1631 | 1094 | 1717 | 1150 | 2372 | 1720 | 0 |
3 |
|
| 0 | 340 | 982 | 445 | 1068 | 501 | 1678 | 841 | 2557 | 0 |
4 |
|
|
| 0 | 982 | 982 | 1068 | 1068 | 1143 | 1678 | 1483 | 0 |
5 |
|
|
|
| 0 | 105 | 105 | 164 | 696 | 501 | 1575 | 0 |
6 |
|
|
|
|
| 0 | 86 | 86 | 666 | 696 | 1275 | 0 |
7 |
|
|
|
|
|
| 0 | 56 | 610 | 393 | 1489 | 0 |
8 |
|
|
|
|
|
|
| 0 | 610 | 610 | 1219 | 0 |
9 |
|
|
|
|
|
|
|
| 0 | 340 | 879 | 0 |
10 |
|
|
|
|
|
|
|
|
| 0 | 879 | 0 |
11 |
|
|
|
|
|
|
|
|
|
| 0 | 0 |