• 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 备份恢复SqlServer数据库
    ASP.NET MVC3.0 Razor 视图模板 语法
    ASP.NET 缓存
    代码生成框架
    C#中HashTable的用法
    C# 概念 委托和事件
    Web Service 系列 → Web Service 简介
    CDN 内容分发网络
    HarmonyOS开发者创新大赛
    #2020征文手表#【图解鸿蒙】多组示例演示三个样式的组合用法
  • 原文地址:https://www.cnblogs.com/pprp/p/7270862.html
Copyright © 2020-2023  润新知