zoukankan      html  css  js  c++  java
  • POJ 3977 题解

    题目

    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.

    输入格式

    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

    输出格式

    For each data set in the input print two integers, the minimum absolute sum and the number of elements in the optimal subset.

    样例输入

    1
    10
    3
    20 100 -100
    0
    

    样例输出

    10 1
    0 2
    

    题解

    我自己想的话,除了暴力没有别的办法,看了题解,照着打了一遍代码,才能理解这个解法

    具体思想就是,全都暴力会超时,所以分成两半枚举,左半部分枚举完保存,右半部分枚举后在左半部分二分查询。

    这算优化暴力吗,dalao们的暴力也和我的暴力不一样。。。

    这个代码使用了不少STL也是一个学习STL的机会

    代码

    #include <algorithm>
    #include <cstdio>
    #include <map>
    using namespace std;
    #define abs(x) ((x) >= 0 ? (x) : -(x))
    long long arr[40];
    int main() {
        int n;
        while (scanf("%d", &n), n) {
            for (int i = 0; i < n; i++) scanf("%lld", &arr[i]);
            pair<long long, long long> ans(abs(arr[0]), 1);
            map<long long, long long> m;
            map<long long, long long>::iterator it;
            int nl = n >> 1, nr = n - (n >> 1);
            for (int i = 1; i < (1 << nl); i++) {
                long long sum = 0, cnt = 0;
                for (int j = 0; j < nl; j++) {
                    if ((i >> j) & 1) sum += arr[j], cnt++;
                }
                long long sum1 = abs(sum);
                if (sum1 < ans.first || (sum1 == ans.first && cnt < ans.second)) ans = make_pair(sum1, cnt);
                if (m[sum]) m[sum] = min(m[sum], cnt);
                else m[sum] = cnt;
            }
            for (int i = 1; i < (1 << nr); i++) {
                long long sum = 0, cnt = 0;
                for (int j = 0; j < nr; j++)
                    if ((i >> j) & 1) sum += arr[j + nl], cnt++;
                long long sum1 = abs(sum);
                if (sum1 < ans.first || (sum1 == ans.first && cnt < ans.second)) ans = make_pair(sum1, cnt);
                it = m.lower_bound(-sum);
                if (it != m.end()) {
                    long long s = abs(it->first + sum), t = it->second + cnt;
                    if (s < ans.first || (s == ans.first && t < ans.second))
                        ans = make_pair(s, t);
                }
                if (it != m.begin()) {
                    it--;
                    long long s = abs(it->first + sum), t = it->second + cnt;
                    if (s < ans.first || (s == ans.first && t < ans.second))
                        ans = make_pair(s, t);
                }
            }
            printf("%lld %lld
    ", ans.first, ans.second);
        }
        return 0;
    }
    
  • 相关阅读:
    自己写的一些公共js方法
    node(03)--利用 HTTP 模块 URl 模块 PATH 模块 FS 模块创建一个 WEB 服务器
    node(03 fs文件模块)
    node (02 CommonJs 和 Nodejs 中自定义模块)顺便讲讲module.exports和exports的区别 dependencies 与 devDependencies 之间的区别
    node.js (01http 模块 url 模块)
    Ubuntu 16.04 下python2和python3及对应的pip的方法
    MySQL划重点-查询-聚合
    MySQL划重点-查询-条件
    MySQL命令
    使用Navicat for Mysql连接装在虚拟机Ubuntu16.04上的mysql服务器
  • 原文地址:https://www.cnblogs.com/youxam/p/poj3977.html
Copyright © 2011-2022 走看看