题目大意:给你一堆积木,选择其中的某些来组成两个相同高度的塔(对于某块积木,可以放在塔1,可以放在塔2,也可以都不放),问你最大组成的高度是多少?
用f[i][j]:表示左塔高度-右塔高度=j时。左塔高度+右塔高度的和的最大值。
f[i+1][s]=max(f[i][s], f[i+1][s]); //不放
f[i+1][s+a[i+1]]=max(f[i+1][s+a[i+1]], f[i][s]+a[i+1]); //放左
f[i+1][s-a[i+1]]=max(f[i+1][s-a[i+1]], f[i][s]+a[i+1]); //放右
#pragma GCC optimize(3, "Ofast", "inline")
#include<bits/stdc++.h>
using namespace std;
int a[1005], f[100][20005], g[100][20005];
int main() {
int n; scanf("%d", &n);
for(int i=1; i<=n; i++){
scanf("%d", &a[i]);
}
memset(f, 0x8f, sizeof(f));
f[0][10000]=0;
for(int i=0; i<n; i++){
for(int s=0; s<20005; s++){
if(f[i][s]>f[i+1][s]){
f[i+1][s]=f[i][s];
g[i+1][s]=0;
}
if(f[i][s]+a[i+1]>f[i+1][s+a[i+1]]){
f[i+1][s+a[i+1]]=f[i][s]+a[i+1];
g[i+1][s+a[i+1]]=1;
}
if(f[i][s]+a[i+1]>f[i+1][s-a[i+1]]){
f[i+1][s-a[i+1]]=f[i][s]+a[i+1];
g[i+1][s-a[i+1]]=2;
}
}
}
printf("%d\n", f[n][10000]/2);
int s=10000;
vector<int> v1, v2;
while(n){
if(g[n][s]==0){
}
else if(g[n][s]==1){
v1.push_back(a[n]);
s-=a[n];
}
else if(g[n][s]==2){
v2.push_back(a[n]);
s+=a[n];
}
n--;
}
printf("塔一:");
for(auto x: v1){
printf("%d ", x);
}
printf("\n");
printf("塔二:");
for(auto x: v2){
printf("%d ", x);
}
printf("\n");
return 0;
}

京公网安备 11010502036488号