A、B两伙马贼意外地在一片沙漠中发现了一处金矿,双方都想独占金矿,但各自的实力都不足以吞下对方,经过谈判后,双方同意用一个公平的方式来处理这片金矿。处理的规则如下:他们把整个金矿分成n段,由A、B开始轮流从最左端或最右端占据一段,直到分完为止。
马贼A想提前知道他们能分到多少金子,因此请你帮忙计算他们最后各自拥有多少金子?(两伙马贼均会采取对己方有利的策略)
输入
测试数据包含多组输入数据。输入数据的第一行为一个正整数T(T<=20),表示测试数据的组数。然后是T组测试数据,每组测试数据的第一行包含一个整数n,下一行包含n个数(n <= 500 ),表示每段金矿的含金量,保证其数值大小不超过1000。
| 样例输入
2 6 4 7 2 9 5 2 10 140 649 340 982 105 86 56 610 340 879
|
输出
对于每一组测试数据,输出一行"Case #id: sc1 sc2",表示第id组数据时马贼A分到金子数量为sc1,马贼B分到金子数量为sc2。详见样例。
| 样例输出
Case #1: 18 11 Case #2: 3206 981
|
时间限制 C/C++语言:1000MS 其他语言:3000MS | 内存限制 C/C++语言:65536KB 其他语言:589824KB |
下面代码是实现,说下解题思路和代码说明:由于A,B都想取得最优,这是个博弈问题,所以把它把缩小到2个数字,前两个数字取最大max1,次大的max2,由于都想取最优,所以后选的那个人必然选的的是次大的数字,比较两个最大数选择次大的给后者,那么前两项和减去次大的就是第一个人选的最优数字。
还需要用一个数组记录前n项和,sum【i】代表前i项的数字和(i从1到n)。data【i】代表标号i数字的值,代表是金子的含金量(i从1到n)
当有4个数字的时候,还是使用上面的方法比较第1,2 第2,3 第3,4 然后用两项和减去次大数字重新更新data数组值,然后范围缩小到比较3个最大值,再利用两两比较的方法然后用前三项和减去前两个的次大值,后三项和减去后两个的次大之,重新更新data数据这样,data里面存储两个都是累加的最大值,然后再利用两两比较的方法,用4项和减去次大的值就是第一个人选择的所有最大值的累加和。
PS:这道题好难,想了好久。。。。
具体选取流程如图:
import java.util.Scanner;
public class Main {
public static void result(int T,int[] data,int n){
int point=n;
int sum[]=new int[n+1];
sum[0]=0;
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+data[i];
}
int k=1;
while(point!=1){
for(int i=1;i<point;i++){
data[i]=sum[i+k]-sum[i-1]-min(data[i],data[i+1]);
}
k++;
point--;
}
System.out.println("Case #"+T+": "+data[1]+" "+(sum[n]-data[1]));
}
public static int min(int a,int b){
int x=a<b?a:b;
return x;
}
@SuppressWarnings("resource")
public static void main(String[] args) {
int T=0;
int n=0;
Scanner scanner;
scanner=new Scanner(System.in);
try{
if(scanner.hasNext()){
T=scanner.nextInt();
if(T>20)
return;
}
for(int i=1;i<=T;i++){
if(scanner.hasNext()){
n=scanner.nextInt();
if(n>500) break;
int[] data=new int[n+1];
for(int j=1;j<=n;j++){
data[j]=scanner.nextInt();
if(data[j]>1000) return;
}
result(i,data,n);
}
}
}catch(Exception e){
}
}
}
时间空间复杂度还可以