ZOJ2868【折半】

来源:互联网 发布:淘宝运费模板删不了 编辑:程序博客网 时间:2024/06/05 06:16

题意:
把一堆数分成两堆,使得两堆的差值最小。
思路:
先把一堆数分成两堆,然后用个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\n",res);    }    return 0;}



0 0
原创粉丝点击