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;
    }
    


    东北日出西边雨 道是无情却有情
  • 相关阅读:
    Effective C++ 学习一
    JavaScript 定义类和继承类的基本步骤
    Vararg collection Factory Method
    apache之httpd启动、终止、重启小结
    Thinking in C++ 学习笔记[1]
    Creational Pattern 之 Abstract Factory
    Perl WEB 开发之 Template
    C语言博客作业数据类型
    C语言博客作业一二维数组
    C语言博客作业函数
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8367146.html
Copyright © 2011-2022 走看看