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


    东北日出西边雨 道是无情却有情
  • 相关阅读:
    DataGridView中DataGridViewComDaboBoxColumn控件点击一次即可显示下拉菜单
    Django2.X报错-------ModuleNotFoundError: No module named 'django.core.urlresolvers'
    C#控件——批量化隐藏或显示同类型控件
    Python——Django运行问题
    关于VS2010 在设计窗口时控件消失问题
    DataGridView操作小记(1)
    c#_生成图片式验证码
    日常杂记——C#验证码
    DataGridView添加的数据最后一步无法生效的问题。
    request.getRequestDispatcher().forward(request,response)和response.sendRedirect()的区别
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8367146.html
Copyright © 2011-2022 走看看