题意
给定一个长度为 n n n 的数列,两个人可以从数列的两端取数,每个人都选取最优解,第一个人取到的数的和为 x x x,第二个人取到的数的和为 y y y,求 x − y x-y x−y。
解决
本题和 这题 有些像,区间动态规划,时间复杂度 O ( n 2 ) O(n^2) O(n2)。
f i , j \mathit{f}_{i,j} fi,j 表示在从 i i i 到 j j j 的区间里第一个人能取到的数的和的最大值。
同时要维护一个 s u m sum sum 数组, s u m i , j \mathit{sum}_{i,j} sumi,j 表示在从 i i i 到 j j j 的区间里的数的和。
初始化过程如下:
f i , i = a i \mathit{f}_{i,i}=a_i fi,i=ai, s u m i , i = a i \mathit{sum}_{i,i}=a_i sumi,i=ai
动态规划过程如下:
循环枚举长度 i i i,循环枚举起始位置 j j j。
f j , i + j = s u m j , i + j − min ( f j , i + j − 1 , f j + 1 , i + j ) \mathit{f}_{j,i+j}=\mathit{sum}_{j,i+j}-\min(\mathit{f}_{j,i+j-1},\mathit{f}_{j+1,i+j}) fj,i+j=sumj,i+j−min(fj,i+j−1,fj+1,i+j)
因为第一个人取到 x = f 1 , n x=\mathit{f}_{1,n} x=f1,n,而所有书的和为 s u m 1 , n \mathit{sum}_{1,n} sum1,n,所以第二个人取到的数和为 y = s u m 1 , n − f 1 , n y=\mathit{sum}_{1,n}-\mathit{f}_{1,n} y=sum1,n−f1,n,所以结果 x − y = f 1 , n × 2 − s u m 1 , n x-y=\mathit{f}_{1,n}\times 2 - \mathit{sum}_{1,n} x−y=f1,n×2−sum1,n。
代码
#include<bits/stdc++.h>
using namespace std;
long long n,a[3010],f[3010][3010],sum[3010][3010];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],sum[i][i]=a[i],f[i][i]=a[i];
for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) sum[i][j]=sum[i][j-1]+a[j];
for(int i=1;i<n;i++) for(int j=1;i+j<=n;j++)f[j][i+j]=sum[j][i+j]-min(f[j][i+j-1],f[j+1][i+j]);
cout<<f[1][n]*2-sum[1][n];
return 0;
}