原题链接:塔 - 洛谷
思路:
求最大高度 -->想办法维护最大高度
int f[N][M]; //已经分配了第i个积木的时候高度差为j的两个塔中高的那个的高度
四种情况:
1.a[i]哪边都不放,高的塔最高值不变
2.a[i]放在矮的塔而且最后矮的塔还是矮的塔,高的塔值不变
3.a[i]放在高的塔,高的塔更高了,高的塔值加a[i]
4.a[i]放在矮的塔,矮的塔增加了a[i]之后比高的塔高了,这时高的塔的那个值要改变,加j
注意:
1)我们每次的j值都是高的减矮的差值,即我们不会让j值成为负数,所以四种情况得判断j与a[i]的关系,j + a[i]还是j - a[i]...
2)如果没有答案,f[n][0]的值不是-INF,而是0,塔的最大高度0,即没有放置任何木块
3)初始化f[][]为-INF,f[0][0] = 0
AC代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define PII pair<int,int>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for(int i = n; i >= 1; ++i)
using namespace std;
const double pi = acos(-1.0);
const int N = 55;
const int M = 5e5 + 10;
int a[N];
int f[N][M]; //已经分配了第i个积木的时候高度差为j的两个塔中高的那个的高度
int main()
{
int n;
scanf("%d", &n);
int sum = 0;
rep(i, n) scanf("%d", &a[i]), sum += a[i];
memset(f, -0x3f, sizeof f);
f[0][0] = 0;
rep(i, n)
for(int j = 0; j <= sum; j++){
f[i][j] = max(f[i - 1][j], f[i - 1][j + a[i]]); //这两个都是高的那个塔的高度不改变
if(j >= a[i]) f[i][j] = max(f[i][j], f[i - 1][j - a[i]] + a[i]);
else f[i][j] = max(f[i][j], f[i - 1][a[i] - j] + j); //自己画一下图,这里对应的是把矮的那个加a[i]然后矮的那个变成了高的,与原来高的高j
}
if(f[n][0]) printf("%d", f[n][0]);
else printf("-1");
return 0;
}