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

    Subset
    Time Limit: 30000MS        Memory Limit: 65536K
    Total Submissions: 6754        Accepted: 1277

    Description
    Given a list of N integers with absolute values no larger than 1015, 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.

    Input
    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 1015 in absolute value and separated by a single space. The input is terminated with N = 0

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

    Sample Input

    1
    10
    3
    20 100 -100
    0

    Sample Output

    10 1
    0 2

    Source
    Seventh ACM Egyptian National Programming Contest

    题解:给出n个数,让你取出一个子集,使子集和的绝对值最小,如果有多个构成相同绝对值的方案,取子集个数最小的

    求最小绝对值和最小大小

    题解:数据范围可以猜出是折半枚举,前一半的数可以在len×2^(n/2)内求出,然后再暴力枚举后一半的和sum,在前一半的所有答案中找出与-sum最相近的两个数,对于sum所产生的贡献,答案肯定只会由这两个数+sum影响。当然还要考虑空集的情况,也就是只取前面或者只取后面

    代码如下:

    #include<map>
    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lson ch[x][0]
    #define rson ch[x][1]
    #define hi puts("hi!");
    #define int long long
    #define mp make_pair
    #define pii pair<int,int>
    using namespace std;
    
    int n,len1,len2,a[40];
    map<int,int> m;
    
    long long absl(long long x)
    {
        return x>0ll?x:-x;
    }
    
    signed main()
    {
        while(~    scanf("%lld",&n)&&n)
        {
            m.clear();
            pii ans=mp(1e18,0ll);
            for(int i=0;i<n;i++) scanf("%lld",&a[i]);
            len1=n/2;
            len2=n-len1;
            for(int i=1;i<1<<len1;i++)
            {
                int cnt=0,sum=0;
                for(int j=0;j<len1;j++)
                {
                    if(i&(1<<j))
                    {
                        cnt++;
                        sum+=a[j];
                    }
                }
                if(!m.count(sum)||m[sum]>cnt) m[sum]=cnt;
                if(ans>mp(absl(sum),cnt)) ans=mp(absl(sum),cnt);
            }
            for(int i=1;i<1<<len2;i++)
            {
                int cnt=0,sum=0;
                for(int j=0;j<len2;j++)
                {
                    if(i&(1<<j))
                    {
                        cnt++;
                        sum+=a[len1+j];
                    }
                }
                if(ans>mp(absl(sum),cnt)) ans=mp(absl(sum),cnt);
                map<long long,long long>::iterator it=m.lower_bound(-sum);
                if(it!=m.end())
                {
                    if(ans>mp(absl(sum+it->first),cnt+it->second))
                    {
                        ans=mp(absl(sum+it->first),cnt+it->second);
                    }
                }
                if(it!=m.begin()) it--;
                if(it!=m.end())
                {
                    if(ans>mp(absl(sum+it->first),cnt+it->second))
                    {
                        ans=mp(absl(sum+it->first),cnt+it->second);
                    }
                }
            }
            printf("%lld %lld
    ",ans.first,ans.second);
        }
    }
  • 相关阅读:
    深入理解javascript原型和闭包(10)——this
    深入理解javascript原型和闭包(9)——简述【执行上下文】下
    深入理解javascript原型和闭包(8)——简述【执行上下文】上
    深入理解javascript原型和闭包(7)——原型的灵活性
    golang 处理 json 结构体
    git push 时用户的配置
    vscod如何自定义 python虚拟环境
    Python实现图片的base64编码
    解决vscode中golang插件依赖安装失败问题
    (转)vscode实现markdown流程图
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/9626529.html
Copyright © 2011-2022 走看看