题意:
把一堆数分成两堆,使得两堆的差值最小。
思路:
先把一堆数分成两堆,然后用个set存一堆的所有组合,枚举第一堆的状态,二分查找第二堆接近half_value。
瞎说时间复杂度:O(2^17*34);
(代码来着某位神犇)
#include<iostream> #include<set> #include<queue> #include<cstdio> #include<math.h> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; typedef pair<int,int> PII; using namespace std; int n; vector<int>a,b; set<int>ss; int main() { int T; scanf("%d",&T); while(T--) { int i=0,x,ans=0; a.clear();b.clear(); scanf("%d",&n); for(;i<n/2;i++) { scanf("%d",&x);ans+=x; a.push_back(x); } for(;i<n;i++) { scanf("%d",&x);ans+=x; b.push_back(x); } int half=ans/2,sum,res; int sz=b.size(); int num=(1<<sz); ss.clear(); for(i=0;i<num;i++) { sum=0; for(int p=0;p<sz;p++) if(i&(1<<p)) sum+=b[p]; ss.insert(sum); } res=-10000000; sz=a.size(); num=(1<<sz); set<int>::iterator it; for(i=0;i<num;i++) { sum=0; for(int p=0;p<sz;p++) if(i&(1<<p)) sum+=a[p]; if(sum>half) continue; int diff=half-sum; it=ss.lower_bound(diff); if((*it)==diff) { res=half; break; } if(it==ss.begin()) continue; it--; if((sum+(*it))>res) res=sum+(*it); } res=ans-2*res; printf("%d ",res); } return 0; }