zoukankan      html  css  js  c++  java
  • 折半枚举

    Given a list of N integers with absolute values no larger than 10 15, find a non empty subset of these numbers which minimizes the absolute value of the sum of its elements. In case there are multiple subsets, choose the one with fewer elements.
    Input
    The input contains multiple data sets, the first line of each data set contains N <= 35, the number of elements, the next line contains N numbers no larger than 10 15 in absolute value and separated by a single space. The input is terminated with N = 0
    Output
    For each data set in the input print two integers, the minimum absolute sum and the number of elements in the optimal subset.
    Sample Input
    1
    10
    3
    20 100 -100
    0
    Sample Output
    10 1
    0 2

    题目分析 : 给你 35 个数字,每个数字只有选或者不选,问你选出数和的绝对值最小。
    思路分析 :
      分成两组去枚举,对于每一组都可以枚举出所有的情况,对于第二组,这里可以排个序,然后在去重,查的时候二分。然后 map 可以就用来优化二分。      
      
    代码示例 :
    const int eps = 1e6+5;
    const double pi = acos(-1.0);
    const int inf = 1<<29;
    #define Max(a,b) a>b?a:b
    #define Min(a,b) a>b?b:a
    #define ll long long
    
    ll pre[50];
    struct node
    {
        ll num;
        int cnt;
    }a[eps];
    
    map<ll, int>mp;
    
    ll fb(ll x){
        return x<0?-x:x;
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int n;
        
        while(~scanf("%d", &n) && n){
            mp.clear(); 
            for(int i = 1; i <= n; i++){
                scanf("%lld", &pre[i]);
            } 
            int n1 = n / 2;
            int n2 = n - n1;
            
            ll ans = 99999999999999999;
            int len = 99999;
            for(int i = 0; i < (1<<n1); i++){
                int p = i;
                ll sum = 0;
                int cnt = 0;
                for(int j = 1; j <= n1; j++){
                    if (p & 1) {
                        sum += pre[j];
                        cnt++;
                    }
                    p >>= 1;
                }
                a[i].num = sum;
                a[i].cnt = cnt;
                
                if (i == 0) continue;
                ll f = fb(a[i].num);
                if (f < ans) {ans = f; len = a[i].cnt;}
                else if (f == ans) len = min(len, a[i].cnt); 
            }
    
            for(int i = 1; i < (1<<n2); i++){
                int p = i;
                ll sum = 0;
                int cnt = 0;
                for(int j = 1+n1; j <= n1+n2; j++){
                    if (p & 1) {
                        sum += pre[j];
                        cnt++;
                    }
                    p >>= 1;
                }
                if (mp.count(sum)) mp[sum] = min(mp[sum], cnt);
                else mp[sum] = cnt;
            }
    
            map<ll, int>::iterator it;
            it = mp.begin();
            ll f = fb(it->first);
            if (f < ans) {ans = f; len = it->second;}
            else if (f == ans) len = min(len, it->second);
            for(int i = 0; i < (1<<n1); i++){
                if (mp.count(-a[i].num)){
                    if (ans == 0) len = min(len, a[i].cnt+mp[-a[i].num]);
                    else len = a[i].cnt + mp[-a[i].num];
                    ans = 0;
                }
                else {
                    it = mp.lower_bound(-a[i].num);
                    ll f = it->first + a[i].num;
                    f = fb(f);
                    if (f < ans) {
                        ans = f;
                        len = it->second + a[i].cnt;
                    }
                    else if (f == ans) len = min(len, it->second+a[i].cnt);
                    
                    it--;
                    f = it->first + a[i].num;
                    f = fb(f);
                    if (f < ans) {
                        ans = f;
                        len = it->second + a[i].cnt;
                    }
                    else if (f == ans) len = min(len, it->second+a[i].cnt);
                } 
            } 
            printf("%lld %d
    ", ans, len);
        }
        
        return 0;
    }
    


    东北日出西边雨 道是无情却有情
  • 相关阅读:
    第6月第4天 AVMutableComposition AVMutableVideoComposition
    error: WatchKit App doesn't contain any WatchKit Extensions whose WKAppBundleIdentifier matches
    领导力和管理的区别是什么?
    小企业如何做好员工管理?
    市场营销案例书籍,市场营销必看的书籍推荐
    情商书籍排行榜:这6本书让你更好地做自己
    市场营销原理,看完这本书你才能懂什么叫市场营销
    能帮你提高情商的书籍推荐
    销售人员最该看的书:《销售管理必读12篇》
    适合初学者看的管理类书籍推荐
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8367146.html
Copyright © 2011-2022 走看看