# How much weight can you lift?

## Python 2, $$\ O(2^{\frac{|W|}2} \cdot |B| \cdot |W| + |W|^2) \$$, 203 bytes

Naive implementation, looks at all combinations of possible weights $$\W\$$ and barbells $$\B\$$.

lambda B,W,T:min([(w+w[::-1],b)for w in p(sorted(sum([W.count(x)/2*[x]for x in set(W)],[])))for b in B],key=lambda(a,b):((T-sum(a)-b)**2,len(a)))
p=lambda l:l and[l[:1]+x for x in p(l[1:])]+p(l[1:])or[l]


Try it online!

### Ungolfed

def f(Barbells, Weights, Target):
# For every pair of same weights keep one, order them ascending
usable_weights = concat([Weights.count(x)/2 * [x] for x in set(Weights)])
usable_weights = sorted(usable_weights)

# list all possible combinations of symmetric weights and barbells
possible_setups = [(w+w[::-1], b)for w in powerset(usable_weights)for b in Barbells]

# Find the one with the weight being the closest to the target,
# on a tie take the one with the lowest number of weights
return min(possible_setups, key=lambda(a,b): ((Target - sum(a) - b)**2, len(a)))

concat = lambda ls:sum(ls, [])
powerset = lambda l:l and [l[:1]+x for x in powerset(l[1:])]+powerset(l[1:]) or [[]]


Try it online!

## C++ (gcc), $$\ O(2^{\frac{|P|}4} \times (|B| + \frac{|P|}2)) \$$, 933 bytes

### Input/Output Format

Takes as input a vector of plates $$\ P \$$, a vector of barbells $$\ B \$$, and a target weight $$\ W \$$. It outputs the plate arrangement on the first line, and the barbell on the second line.

#include <bits/stdc++.h>
using namespace std;using d=double;
int f(auto b,auto p,d w){
unordered_map<d,int>u;vector<d>s,A,B;
for(auto i:p)u[i]++;
for(auto i:u)while((i.second-=2)>=0)s.push_back(i.first*2);
int z=s.size(),i,j,k;vector<pair<d,vector<d>>>x(1<<z/2),y(1<<z/2+1);d m=DBL_MAX,n,r;
for(i=0,k=1;i<z/2;i++){
for(j=0;j<k;j++)x[j+k]=x[j];
for(;j<k*2;j++)x[j].first+=s[i],x[j].second.push_back(s[i]/2);
auto _=x.begin();inplace_merge(_,_+k,_+k*2);k*=2;
}
for(k=1;i<z;i++){
for(j=0;j<k;j++)y[j+k]=y[j];
for(;j<k*2;j++)y[j].first+=s[i],y[j].second.push_back(s[i]/2);
auto _=y.begin();inplace_merge(_,_+k,_+k*2);k*=2;
}
for(auto f:b)
for(i=0,j=(1<<z-z/2)-1;i<1<<z/2&&j>=0;n>w?j--:i++){
n=x[i].first+y[j].first+f;
if(abs(n-w)<m)r=f,A=x[i].second,B=y[j].second,m=abs(n-w);
}
A.insert(A.end(),B.begin(),B.end());
sort(A.begin(),A.end());for(auto i:A)cout<<i<<' ';
reverse(A.begin(), A.end());for(auto i:A)cout<<i<<' ';
cout<<'\n'<<r;
}


Try it online!

### Explanation

The algorithm calculates all possible subset sums $$\ S \$$ of $$\ P \$$, and then finds the sum $$\ s + b \$$ which is closest to $$\ W \$$, where $$\ s \$$ and $$\ b \$$ are elements in $$\ S \$$ and $$\ B \$$, respectively. Using the meet-in-the-middle approach decreases the complexity quite a bit. (I'm aware this code is super long, and I'll try to shrink it a bit eventually).