1. 程式人生 > >[luoguP2858] [USACO06FEB]奶牛零食Treats for the Cows(DP)

[luoguP2858] [USACO06FEB]奶牛零食Treats for the Cows(DP)

turn pri class 分享 blank .org splay == pla

傳送門

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

遞推順序不好求,所以選擇記憶化搜索。

——代碼

技術分享
 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 }
View Code

[luoguP2858] [USACO06FEB]奶牛零食Treats for the Cows(DP)