https://www.luogu.org/problemnew/show/P2734
数据范围比较小,二位DP可做,而luogu 3004,虽然几乎一模一样(只是数据范围大点),则需要压维。
定义f[i][j]表示从区间[i,j]的最大取数总和,那么既然每个人都是取最优的方案数,那么它可以由f[i+1][j]和f[i][j-1]推来。
若f[i][j]是由上一个区间f[i+1][j]得来(取较短序列的左端),它的最大值由[i,j]区间总和减去序列左端的值,若由区间[i,j-1]得来的话,就是去上个序列右边的值,方法与其相同。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; #define N int(1e5+2) #define M int(1e2+2) int n,a[N],dp[M][M],sum[M]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]),dp[i][i]=a[i],sum[i]=sum[i-1]+a[i]; for(int i=n-1;i>=1;i--) { for(int j=i+1;j<=n;j++) { dp[i][j]=max(sum[j]-sum[i-1]-dp[i+1][j],sum[j]-sum[i-1]-dp[i][j-1]); } } printf("%d %d",dp[1][n],sum[n]-dp[1][n]); }
足够应付这道题了,若想进一步优化空间复杂度 戳这儿!!