• poj 3977 子集


    题目

    题意:在一个集合中找到一个非空子集使得这个子集元素和的绝对值尽量小,和绝对值相同时保证元素个数尽量小

    分析:1.二分枚举的思想,先分成两个集合;

           2.枚举其中一个集合中所有的子集并且存到数组中,并排序;

          3.枚举另一个集合中所有的子集并且与第一个集合中的合适子集相加(可以通过二分查找在数组中找到最合

    适的元素)

      4.这个题特别坑的地方是不能用abs库函数,只能手写

    AC代码:

    #include<stdio.h>
    #include<map>
    #include<algorithm>
    using namespace std;
    #define ll long long
    ll a[50];
    ll Abs(ll x)
    {
        return x<0?-x:x;
    }
    int main( )
    {
      int n;
      while(scanf("%d",&n)!=EOF)
      {    
          if(n==0)
            break;
          for(int i=0 ; i<n ; i++)
           scanf("%lld",&a[i]);
          int n2=n/2;
          pair<ll,int> ans(Abs(a[0]),1);
          map<ll,int>M;
          map<ll,int>::iterator it;
          for(int i=1 ; i<1<<n2 ; i++)
          {
              ll sum=0;int cnt=0;
              for(int j=0 ; j<n2 ; j++)
              {
                  if(i>>j&1)
                  {
                      sum+=a[j];
                      cnt++;
                  }
              }
              ans = min(ans,make_pair(Abs(sum),cnt));
              if(M[sum])
                M[sum]=min(M[sum],cnt);
              else
                M[sum]=cnt;
          }
          for(int i=1 ; i<1<<(n-n2) ; i++)
          {
              ll sum=0;int cnt=0;
              for(int j=0 ; j<n-n2 ; j++)
              {
                  if(i>>j&1)
                  {
                      sum+=a[j+n2];
                      cnt++;
                  }
    
              }
              ans=min(ans,make_pair(Abs(sum),cnt));
              it = M.lower_bound(-sum);
              if(it != M.end())
                ans = min(ans,make_pair(Abs(sum+it->first),cnt+it->second));
              if(it != M.begin())
                {
                    it--;
                   ans = min(ans,make_pair(Abs(sum+it->first),cnt+it->second));
                }
                
          }
          printf("%lld %d
    ",ans.first,ans.second);
      }
      return 0;
    
    }
    View Code

    带解析

    #include <iostream>
    #include <algorithm>
    #include <limits>
    #include <map>
    using namespace std;
    typedef long long LL;
    #define MAX_N 36
    LL number[MAX_N];
     
    LL ll_abs(const LL& x)    // damn it! error C3861: 'llabs': identifier not found
    {
        return x >= 0 ? x : -x;
    }
     
    ///////////////////////////SubMain//////////////////////////////////
    int main(int argc, char *argv[])
    {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    #endif
        int N;
        while (cin >> N && N)
        {
            for (int i = 0; i < N; ++i)
            {
                cin >> number[i];
            }
            map<LL, int> dp;    // sum的值<->集合元素个数,这里不是绝对值
            pair<LL, int> result(ll_abs(number[0]), 1);    // 最优解
            for (int i = 0; i < 1 << (N / 2); ++i)    // 枚举前 N / 2
            {
                LL sum = 0;
                int num = 0;
                for (int j = 0; j < N / 2; ++j)
                {
                    if ((i >> j) & 1)
                    {
                        sum += number[j];
                        ++num;
                    }
                }
                if (num == 0)
                {
                    continue;
                }
                result = min(result, make_pair(ll_abs(sum), num));
                map<LL, int>::iterator it = dp.find(sum);
                if (it != dp.end())
                {
                    it->second = min(it->second, num);
                }
                else
                {
                    dp[sum] = num;
                }
            }
     
            for (int i = 0; i < 1 << (N - N / 2); ++i)    // 枚举剩下的
            {
                LL sum = 0;
                int num = 0;
                for (int j = 0; j < N - N / 2; ++j)
                {
                    if ((i >> j) & 1)
                    {
                        sum += number[N / 2 + j];
                        ++num;
                    }
                }
                if (num == 0)
                {
                    continue;
                }
                result = min(result, make_pair(ll_abs(sum), num));
                // 找寻跟-sum最相近的结果
                map<LL, int>::iterator it = dp.lower_bound(-sum);    // 返回大于或等于-sum的第一个元素位置
                if (it != dp.end())
                {// 可能是该位置
                    result = min(result, make_pair(ll_abs(sum + it->first), num + it->second));
                }
                if (it != dp.begin())
                {// 或比该元素小一点点的
                    --it;
                    result = min(result, make_pair(ll_abs(sum + it->first), num + it->second));
                }
            }
            cout << ll_abs(result.first) << ' ' << result.second << endl;
        }
    #ifndef ONLINE_JUDGE
        fclose(stdin);
        fclose(stdout);
        system("out.txt");
    #endif
        return 0;
    }
    View Code
  • 相关阅读:
    Threaten Model
    什么是虚拟主机
    http代理服务器
    什么是https
    缓存的实现原理
    Cookie和Session
    HTTP协议详解
    心路历程——毕设程序mr跑不通的问题
    bash: hadoop:command not found
    Mapreduce 测试自带实例 wordcount
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9047457.html
Copyright © 2020-2023  润新知