zoukankan      html  css  js  c++  java
  • HDU3017 Treasure Division 题解 折半搜索

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3017

    题目大意:

    (n(le 30)) 块硬币((n) 可能是奇数),每块硬币都有一个币值。要求将 (n) 块金币分成两堆,使得两堆硬币币值和的差尽可能地小。输出这个最小的差。

    解题思路:

    暴力搜索的时间复杂度为 (O(2^{30})),会超时,所以考虑使用折半搜索,时间复杂度降为 (O(2 cdot 15 cdot 2^{15}))

    示例代码:

    #include <bits/stdc++.h>
    using namespace std;
    int n;
    long long v[31], ans;
    set<long long> st[16];
    void dfs1(int id, int cnt, long long tmp) {
        if (id > n/2) {
            st[cnt].insert(tmp);
            return;
        }
        dfs1(id+1, cnt, tmp-v[id]);
        dfs1(id+1, cnt+1, tmp+v[id]);
    }
    void dfs2(int id, int cnt, long long tmp) {
        if (id > n) {
            int p = n/2 - max(0, n/2 - cnt);
            assert(p >= 0 && p <= n/2);
            set<long long>::iterator it = st[p].lower_bound(tmp);
            if (it != st[p].end()) {
                int val = *it;
                ans = min(ans, abs(tmp - val));
            }
            if (it != st[p].begin()) {
                it --;
                int val = *it;
                ans = min(ans, abs(tmp - val));
            }
            return;
        }
        dfs2(id+1, cnt, tmp-v[id]);
        dfs2(id+1, cnt+1, tmp+v[id]);
    }
    int main() {
        while (~scanf("%d", &n)) {
            for (int i = 0; i <= n/2; i ++) st[i].clear();
            ans = (1LL<<60);
            for (int i = 1; i <= n; i ++) scanf("%lld", v+i);
            dfs1(1, 0, 0);
            dfs2(n/2+1, 0, 0);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    ELK环境搭建
    django orm 操作表
    django1.11入门
    CentOS7 yum安装python3.6
    完美的【去重留一】SQL
    CentOS7安装docker
    【Jenskins】安装与配置
    【Linux】网卡配置与绑定
    【SaltStack】一些常用模块举例
    【SaltStack】通过Master给Minion安装MySQL
  • 原文地址:https://www.cnblogs.com/quanjun/p/13693998.html
Copyright © 2011-2022 走看看