XJTU轮流取数


在主城站街很久之后,小萌决定不能就这样的浪费时间虚度青春,他打算去打副本。 

这次的副本只有一个BOSS,而且BOSS是不需要击杀的,只需要和它比智力……. 

BOSS会列出一正整数的序列,由小萌先开始,然后两个人轮流从序列的任意一端取数,取得的数累加到积分里,当所有数都取完,游戏结束。 

假设小萌和BOSS都很聪明,两个人取数的方法都是最优策略,问最后两人得分各是多少。

输入

整数个数N

用空格隔开的N个正整数(1 ≤ a[i] ≤ 1000) 

输出 

只有一行,用空格隔开的两个数,小萌的得分和BOSS的得分。 

样例输入:

6
4 7 2 9 5 2

样例输出:

18 11

定义一个数组a[n]接受输入

定义一个矩阵L,L[i][j]代表某人先取,从数组a中下标i到j的数中最大能取的值

如果只有一个数,这个人只能取这个数

即L[i][j]=a[i]

012345
04
17
22
39
45
52

如果有两个数,这个人先取,他会取最大的数

两个数的总和是一定的,也可以看出他取了某个数之后要使得另一个人取的数最小,他才能取得最大

对于从i到j的数来说,这些数的和是一定的,某人只能取两端的数,他要使得自己取得的数总和最大,他就要在取了这个数之后,使得另一个人在剩下的数中取得的最大值最小,而另外一个人的取法是在第一个人取了第i或第j个数后,他会在i+1到j或i到j-1中取最大值,即L[i+1][j]或L[i][j-1]

这样,第一个人取的想法就应该是使得另一个人取的L[i+1][j]和L[i][j-1]中较小的一个值,而他,也就是L[i][j]=max(sum(i,j)-L[i+1][j],sum(i,j)-L[i][j-1])

递推式:

L[i,j]=\left\{\begin{matrix} a[i]& ,i=j\\ max(sum(i,j)-L[i][j-1],sum(i,j)-L[i+1][j])& ,i\neq j \end{matrix}\right.

#include<iostream>

using namespace std;

int L[10][10]={0};

void f(int n,int*a);
void sum(int*a,int i,int j);

int main()
{
	int n;
	cin>>n;
	int a[10];
	for(int i=0;i<n;i++)
	cin>>a[i];
	f(n,a);
	return 0;
}

int s(int *a,int i,int j) 
{
	int sum=0;
	for(int k=i;k<=j;k++)
	sum+=a[k];
	return sum;
}
void f(int n,int*a)
{
	for(int flag=0;flag<=n;flag++)//这里可以看成沿着矩阵对角线进行每一轮的循环,flag代表循环的次数
	//当循环n次时,可以得到L[0][n-1];
	{
		for(int i=0;i<n-flag;i++)//每一次循环从矩阵的第0行开始
		{
			int j=i+flag;//第flag+1次循环时,坐标为(i,i+flag) 
			if(i==j)
			L[i][j]=a[i];
			else
			{
				L[i][j]=max(s(a,i,j)-L[i][j-1],s(a,i,j)-L[i+1][j]);//递推式 
			}
		}
	}
	cout<<L[0][n-1]<<' '<<s(a,0,n-1)-L[0][n-1];
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值