分金子(360公司2017春招真题)

A、B两伙马贼意外地在一片沙漠中发现了一处金矿,双方都想独占金矿,但各自的实力都不足以吞下对方,经过谈判后,双方同意用一个公平的方式来处理这片金矿。处理的规则如下:他们把整个金矿分成n段,由A、B开始轮流从最左端或最右端占据一段,直到分完为止。 

马贼A想提前知道他们能分到多少金子,因此请你帮忙计算他们最后各自拥有多少金子?(两伙马贼均会采取对己方有利的策略)

 

 

输入

 

测试数据包含多组输入数据。输入数据的第一行为一个正整数T(T<=20),表示测试数据的组数。然后是T组测试数据,每组测试数据的第一行包含一个整数n,下一行包含n个数(n <= 500 ),表示每段金矿的含金量,保证其数值大小不超过1000。

 

 

样例输入

 

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){
			
		}
		
		
	}
}

 

时间空间复杂度还可以

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬砖民工金币

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值