题目大意:给你一堆积木,选择其中的某些来组成两个相同高度的塔(对于某块积木,可以放在塔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;
}