题目链接:

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 }

 

相关文章: