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

    链接:

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

    题意:

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

    如果有一样的,取个数最小的 

    题解:

    np难题,但是因为数据小,所以可以通过折半枚举求解

    先枚举前一半的所有情况 用map记录下来,

    然后在枚举后一半的所有情况,再在前一半记录的map里面找相加的和 与0最接近的

    开始我用的set,但是set不好处理重复的

    不过map居然也可以用lower_bound!

    另外poj好像不支持long long的abs 所以要自己写一个

    代码:

     1 #include <map>
     2 #include <set>
     3 #include <cmath>
     4 #include <queue>
     5 #include <stack>
     6 #include <cstdio>
     7 #include <string>
     8 #include <vector>
     9 #include <cstdlib>
    10 #include <cstring>
    11 #include <sstream>
    12 #include <iostream>
    13 #include <algorithm>
    14 #include <functional>
    15 using namespace std;
    16 #define rep(i,a,n) for (int i=a;i<n;i++)
    17 #define per(i,a,n) for (int i=n-1;i>=a;i--)
    18 #define pb push_back
    19 #define mp make_pair
    20 #define all(x) (x).begin(),(x).end()
    21 #define SZ(x) ((int)(x).size())
    22 typedef vector<int> VI;
    23 typedef long long ll;
    24 typedef pair<int, int> PII;
    25 const ll MOD = 1e9 + 7;
    26 const int INF = 0x3f3f3f3f;
    27 const double EPS = 1e-10;
    28 const double PI = acos(-1.0);
    29 const int MAXN = 8010;
    30 // head
    31 
    32 ll list[40];
    33 map <ll, int> mm;
    34 typedef pair<ll, int> pli;
    35 
    36 ll labs(ll x) {
    37     return x >= 0 ? x : -x;
    38 }
    39 
    40 int main() {
    41     int n;
    42     while (cin >> n, n) {
    43         mm.clear();
    44         rep(i, 0, n) scanf("%lld", list + i);
    45         pli ans = mp(1e18, 0);
    46         int n1 = n / 2, n2 = n - n1;
    47         rep(i, 1, 1 << n1) {
    48             ll sum = 0;
    49             int num = 0;
    50             rep(j, 0, n1) if (i&(1 << j)) sum += list[j], num++;
    51             if (!mm[sum] || mm[sum] > num) mm[sum] = num;
    52             pli t = mp(labs(sum), num);
    53             if (t < ans) ans = t;
    54         }
    55         rep(i, 1, 1 << n2) {
    56             ll sum = 0;
    57             int num = 0;
    58             rep(j, 0, n2) if (i&(1 << j)) sum += list[n1 + j], num++;
    59             pli t = mp(labs(sum), num);
    60             if (t < ans) ans = t;
    61             map<ll, int>::iterator k = mm.lower_bound(-sum);
    62             if (k != mm.end()) {
    63                 t = mp(labs((*k).first + sum), num + (*k).second);
    64                 if (t < ans) ans = t;
    65             }
    66             if (k != mm.begin()) --k;
    67             if (k != mm.end()) {
    68                 t = mp(labs((*k).first + sum), num + (*k).second);
    69                 if (t < ans) ans = t;
    70             }
    71         }
    72         cout << ans.first << ' ' << ans.second << endl;
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    自定义TabBarController
    UITabBarController剖析
    IOS中UIScrollView的contentSize、contentOffset和contentInset属性
    iOS开发 剖析网易新闻标签栏视图切换
    transitionFromViewController方法的使用
    ViewController生命周期
    1816. Truncate Sentence
    1290. 二进制链表转整数
    1302. 层数最深叶子节点的和
    102.二叉树的层次遍历
  • 原文地址:https://www.cnblogs.com/baocong/p/6693060.html
Copyright © 2011-2022 走看看