zoukankan      html  css  js  c++  java
  • POJ 3977 Subset(二分+折半枚举)

    题意:有一个N(N <= 35)个数的集合,每个数的绝对值小于等于1015,找一个非空子集,使该子集中所有元素的和的绝对值最小,若有多个,则输出个数最小的那个。

    分析:

    1、将集合中的元素分成两半,分别二进制枚举子集并记录子集所对应的和以及元素个数。

    2、枚举其中一半,二分查找另一半,不断取最小值。

    #pragma comment(linker, "/STACK:102400000, 102400000")
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cmath>
    #include<iostream>
    #include<sstream>
    #include<iterator>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    #include<deque>
    #include<queue>
    #include<list>
    #define Min(a, b) ((a < b) ? a : b)
    #define Max(a, b) ((a < b) ? b : a)
    const double eps = 1e-10;
    inline int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a > b ? 1 : -1;
    }
    typedef long long LL;
    typedef unsigned long long ULL;
    const int INT_INF = 0x3f3f3f3f;
    const int INT_M_INF = 0x7f7f7f7f;
    const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
    const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
    const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
    const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
    const int MOD = 1e9 + 7;
    const double pi = acos(-1.0);
    const int MAXN = 35 + 10;
    const int MAXT = 100000 + 10;
    using namespace std;
    LL a[MAXN];
    map<LL, LL> mp1;
    map<LL, LL> mp2;
    vector<LL> v1;
    vector<LL> v2;
    LL ans, num;
    LL Abs(LL x){
        return x >= 0 ? x : -x;
    }
    void init(){
        mp1.clear();
        mp2.clear();
        v1.clear();
        v2.clear();
    }
    void solve(int l, int r, map<LL, LL> &mp, vector<LL> &v){
        int n = r - l + 1;
        for(int i = 1; i < (1 << n); ++i){
            LL sum = 0;
            LL cnt = 0;
            for(int j = 0; j < n; ++j){
                if(i & (1 << j)){
                    sum += a[l + j];
                    ++cnt;
                }
            }
            if(mp.count(sum))
                mp[sum] = Min(mp[sum], cnt);
            else
                mp[sum] = cnt;
        }
        for(map<LL, LL>::iterator it = mp.begin(); it != mp.end(); ++it){
            v.push_back((*it).first);
            if(Abs((*it).first) < ans){
                ans = Abs((*it).first);
                num = (*it).second;
            }
            else if(ans == Abs((*it).first)){
                num = Min(num, (*it).second);
            }
        }
    }
    void judge(LL x){
        int l = 0, r = v2.size() - 1;
        while(l <= r){
            int mid = l + (r - l) / 2;
            if(Abs(x + v2[mid]) < ans){
                ans = Abs(x + v2[mid]);
                num = mp1[x] + mp2[v2[mid]];
            }
            else if(Abs(x + v2[mid]) == ans){
                num = Min(num, mp1[x] + mp2[v2[mid]]);
            }
            if(x + v2[mid] < 0) l = mid + 1;
            else r = mid - 1;
        }
    }
    int main(){
        int N;
        while(scanf("%d", &N) == 1){
            if(!N) return 0;
            init();
            for(int i = 0; i < N; ++i){
                scanf("%lld", &a[i]);
            }
            if(N == 1){
                printf("%lld 1\n", Abs(a[0]));
                continue;
            }
            ans = LL_INF, num = LL_INF;
            solve(0, N / 2 - 1, mp1, v1);
            solve(N / 2, N - 1, mp2, v2);
            int len = v1.size();
            sort(v2.begin(), v2.end());
            for(int i = 0; i < len; ++i){
                judge(v1[i]);
            }
            printf("%lld %lld\n", ans, num);
        }
        return 0;
    }
    

      

  • 相关阅读:
    实例属性 类属性 实例域 类域
    研究数据集
    static 静态域 类域 静态方法 工厂方法 he use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class 非访问修饰符
    accessor mothod mutator mothod 更改器方法 访问器方法 类的方法可以访问类的任何一个对象的私有域!
    上钻 下钻 切片 转轴 降采样
    识别会话
    Performance Tuning Using Linux Process Management Commands
    Secure Hash Algorithm 3
    grouped differently across partitions
    spark 划分stage Wide vs Narrow Dependencies 窄依赖 宽依赖 解析 作业 job stage 阶段 RDD有向无环图拆分 任务 Task 网络传输和计算开销 任务集 taskset
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/6528421.html
Copyright © 2011-2022 走看看