题目描述
小 A 和小 B 在玩游戏。
初始时,有n个硬币被摆成了一行,从左至右数第i个硬币的价值为ci。
小 A 和小 B 每人一回合,在一个人的回合中,他可以选择当前硬币序列最左侧或者最右侧的硬币,并将他从序列中取出,将其价值累加到自己获得的累计价值中,然后进行另一个人的回合。当硬币全部被取走时,游戏结束。
请求出在双方都尽可能的使自己累计价值最大的情况下,若由小 A 进行第一回合,那么他能获得的累计价值最大是多少。
输入格式
输入的第一行是一个整数 n,代表硬币的个数。
第2到第(n+1) 行,每行一个整数,第(i+1) 行的整数代表第i个硬币的价值ci。
输出格式
输出一行一个整数,代表小 A 能获得的最大累计价值。
输入/输出样例1
输入:
4
30
25
10
35
输出:
60
样例解释
数据范围:对于全部的测试点,1≤n≤5×10^3,1≤ci≤5×10^3。
分析
样例1:
初始时,硬币序列为 {30, 25, 10, 35}。
第一回合,小 A 取走最右侧的硬币,序列变为{30, 25, 10},小 A 的累加价值为 35。
第二回合,小 B 取走最左侧的硬币,序列变为{25, 10},小 B 的累加价值为 30。
第三回合,小 A 取走最左侧的硬币,序列变为 {10},小 A 的累加价值为 35 + 25 = 60。
第四回合,小 B 取走最左侧的硬币,序列变为空,小 B 的累加价值为 30 + 10 = 40,游戏结束。
小 A 获得的最大累计价值为 60。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e3+10;
int a[maxn],f[maxn][maxn],sum[maxn];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
f[i][i]=a[i];
}
for(int len=2;len<=n;len++)
{
for(int i=1;i+len-1<=n;i++)
{
int j=i+len-1;
f[i][j]=sum[j]-sum[i-1]-min(f[i+1][j],f[i][j-1]);
}
}
cout<<f[1][n]<<endl;
return 0;
}