zoukankan      html  css  js  c++  java
  • POJ 3977

    2017-08-01 21:45:19

    writer:pprp

    题目:

    • POJ 3977
    • 给定n个数,求一个子集(非空)
    • 使得子集内元素和的绝对值最小
    • n ≤ 35


    AC代码如下:(难点:枚举出sum)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    
    
    using namespace std;
    
    const int maxn = 40;
    const int INF = 0x3f3f3f3f;
    typedef long long ll;
    int n;
    ll a[maxn];
    int Min = INF;
    
    
    ll ll_abs(ll x)
    {
        return x>=0?x:-x;
    }
    
    int main()
    {
        while(cin >> n && n)
        {
            memset(a,0,sizeof(a));
            for(int i = 0 ; i < n ; i++)
            {
                cin >> a[i];
            }
            map<ll, int>mp; //sum -> cnt
            pair<ll,int>ans(ll_abs(a[0]),1);   //储存最优解
    
            for(int i = 0 ; i < (1<<(n/2)) ; i++)
            {
    
                ll sum = 0;
                int cnt = 0;
                for(int j = 0 ; j < (n/2) ; j++)
                {
                    if((i>>j)&1)
                    {
                        sum += a[j];
                        cnt++;
                    }
                }
    
                if(cnt == 0)
                    continue;
                ans = min(ans,make_pair(ll_abs(sum),cnt));
    
                map<ll, int>::iterator it = mp.find(sum);
    
                if(it != mp.end())
                {
                    //取更小的元素个数
                    it->second = min(it -> second, cnt);
                }
                else
                    mp[sum] = cnt;
    
            }
    
            for(int i = 0 ; i < (1 << (n - n / 2)) ; i++)
            {
                ll sum = 0;
                int cnt = 0;
                for(int j = 0 ; j < (n - n / 2) ; j++)
                {
                    if((i>>j)&1)
                    {
                        sum += a[n / 2 + j];
                        cnt++;
                    }
                }
    
                if(cnt == 0)  continue;
                ans = min(ans, make_pair(ll_abs(sum), cnt));
                
                map<ll, int> ::iterator it = mp.lower_bound(-sum);
    
                if(it != mp.end())
                    ans = min(ans, make_pair(ll_abs(it->first + sum), it->second + cnt));
    
                if(it != mp.begin())
                {
                      it--;
                      ans = min(ans, make_pair(ll_abs(it->first + sum), it->second + cnt) );
                }
            }
            cout << ans.first <<" " << ans.second << endl;
        }
    
        return 0;
    }

     

  • 相关阅读:
    解释 ASP.NET中的Web页面与其隐藏类之间的关系
    B/S与C/S的联系与区别
    三层架构
    列举 ASP.NET页面之间传递值的几种方式
    什么是SQL注入式攻击?如何防范?
    post、get的区别
    Session,ViewState,Application,cookie的区别?
    Vue 09.前后端交互
    Vue 08.webpack中使用.vue组件
    Vue 07.webpack
  • 原文地址:https://www.cnblogs.com/pprp/p/7270862.html
Copyright © 2011-2022 走看看