题目链接:
https://www.nowcoder.com/questionTerminal/040924ba0e64423b8a3fe2f75a56934a
思路:
dp + 滚动数组。
定义状态为(当前第几个砖块, 两堆砖块高度差),于是就变成了和01背包差不多的问题。
初始只有i = 0时,dp[n][i] = 0,否则dp[n][i] = -INF.
dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - a[i]], dp[i + 1][j + a[i]] + a[i]).
(或者dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - a[i]] + a[i], dp[i + 1][j + a[i]]).算哪堆都一样)
注意j不要超出范围。为了避免j为负数,要加个偏移量。
还有滚动数组优化空间。
实现:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 7 const int INF = 0x3f3f3f3f, MAXN = 500000; 8 int a[55], dp[2][2 * MAXN + 1], n; 9 10 bool check(int x) 11 { 12 return x >= -MAXN && x <= MAXN; 13 } 14 15 int solve() 16 { 17 for (int i = -MAXN; i <= MAXN; i++) dp[n & 1][i + MAXN] = -INF; 18 dp[n & 1][MAXN] = 0; 19 for (int i = n - 1; i >= 0; i--) 20 { 21 for (int j = -MAXN; j <= MAXN; j++) 22 { 23 dp[i & 1][j + MAXN] = dp[(i + 1) & 1][j + MAXN]; 24 if (check(j - a[i])) 25 dp[i & 1][j + MAXN] = 26 max(dp[i & 1][j + MAXN], dp[(i + 1) & 1][j - a[i] + MAXN] + a[i]); 27 if (check(j + a[i])) 28 dp[i & 1][j + MAXN] = 29 max(dp[i & 1][j + MAXN], dp[(i + 1) & 1][j + a[i] + MAXN]); 30 } 31 } 32 return dp[0][MAXN]; 33 } 34 35 int main() 36 { 37 cin >> n; 38 for (int i = 0; i < n; i++) 39 { 40 cin >> a[i]; 41 } 42 int x = solve(); 43 if (x > 0) cout << x << endl; 44 else puts("-1"); 45 return 0; 46 }