zoukankan      html  css  js  c++  java
  • POJ 3977 折半枚举

    链接:

    http://poj.org/problem?id=3977

    题意:

    给你n个数,n最大35,让你从中选几个数,不能选0个,使它们和的绝对值最小,如果有一样的,取个数最小的 

    思路:

    子集个数共有2^n个,所以不能全部枚举,但是可以分为两部分枚举;枚举一半的所有情况,然后后一半二分即可;

    代码:

     1 #include"bits/stdc++.h"
     2 #define N 45
     3 using namespace std;
     4 typedef long long LL;
     5 
     6 int n;
     7 LL a[N];
     8 
     9 LL Abs(LL x)
    10 {
    11     return x<0?-x:x;
    12 }
    13 
    14 int main()
    15 {
    16     while(scanf("%d", &n), n)
    17     {
    18         for(int i=0; i<n; i++)
    19             scanf("%I64d", &a[i]);
    20 
    21         map<LL, int> M;
    22         map<LL, int>::iterator it;
    23         pair<LL, int> ans(Abs(a[0]), 1);
    24 
    25         for(int i=1; i<1<<(n/2); i++)
    26         {
    27             LL sum = 0;int cnt = 0;
    28             for(int j=0; j<(n/2); j++)
    29             {
    30                 if((i>>j)&1)
    31                 {
    32                     sum += a[j];
    33                     cnt ++;
    34                 }
    35             }
    36             ans = min(ans, make_pair(Abs(sum), cnt));///全部是前半部分的;
    37             if(M[sum])///更新cnt为小的;
    38                 M[sum] = min(M[sum], cnt);
    39             else
    40                 M[sum] = cnt;
    41         }
    42 
    43         for(int i=1; i<1<<(n-n/2); i++)
    44         {
    45             LL sum = 0;int cnt = 0;
    46             for(int j=0; j<(n-n/2); j++)
    47             {
    48                 if((i>>j)&1)
    49                 {
    50                     sum += a[j+n/2];
    51                     cnt ++;
    52                 }
    53             }
    54             ans = min(ans, make_pair(Abs(sum), cnt));///全部是后半部分的;
    55 
    56             it = M.lower_bound(-sum);///找到第一个大于-sum的位置,然后取两种情况的最小值;
    57 
    58             if(it != M.end())
    59                 ans = min(ans, make_pair(Abs(sum+it->first), cnt+it->second));
    60             if(it != M.begin())
    61             {
    62                 it--;
    63                 ans = min(ans, make_pair(Abs(sum+it->first), cnt+it->second));
    64             }
    65         }
    66         printf("%I64d %d
    ", ans.first, ans.second);
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    MYSQL索引优化法则
    关于String对象到底占多少字节?
    类加载的时机
    HotSpot 虚拟机对象探秘
    JVM 内存结构
    Tomcat10-记录踩坑
    笔记 | 吴恩达新书《Machine Learning Yearning》
    图像分割论文 | DRN膨胀残差网络 | CVPR2017
    除了边缘场景,你还能在哪里使用K3s?
    基础指南:如何在K3s中配置Traefik?
  • 原文地址:https://www.cnblogs.com/mj-liylho/p/9453395.html
Copyright © 2011-2022 走看看