[luoguP2858] [USACO06FEB]奶牛零食Treats for the Cows(DP)
f[i][j][k] 表示 左右两段取到 i .... j 时,取 k 次的最优解
可以优化 k 其实等于 n - j + i
则 f[i][j] = max(f[i + 1][j] + a[i] * (n - j + i), f[i][j - 1] + a[j] * (n - j + i))
边界 f[i][i] = a[i] * n
递推顺序不好求,所以选择记忆化搜索。
——代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <iostream> 3 4 const int MAXN = 2001; 5 int n; 6 int a[MAXN], f[MAXN][MAXN]; 7 8 inline int read() 9 { 10 int x = 0, f = 1; 11 char ch = getchar(); 12 for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; 13 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; 14 return x * f; 15 } 16 17 inline int max(int x, int y) 18 { 19 return x > y ? x : y; 20 } 21 22 inline int dp(int x, int y) 23 { 24 if(f[x][y]) return f[x][y]; 25 if(x == y) return f[x][y] = a[x] * n; 26 else return f[x][y] = max(dp(x + 1, y) + a[x] * (n - y + x), dp(x, y - 1) + a[y] * (n - y + x)); 27 } 28 29 int main() 30 { 31 int i; 32 n = read(); 33 for(i = 1; i <= n; i++) a[i] = read(); 34 printf("%d\n", dp(1, n)); 35 return 0; 36 }