c++ - 更新 std::set 以仅保留最小值

标签 c++ algorithm stl permutation stdset

对于某些算法,我必须在 n 整数元素集的所有排列上调用函数 f 范围从 1 到 n。最后,我对产生最小 f 值的 100 个排列感兴趣。

我能找到的最佳解决方案如下。但它有一个严重的缺点。当 n 增加时,fPerm 会消耗大量内存。

修剪 fPerm 的最佳解决方案是什么,以便它只保留迄今为止找到的最好的 100 个解决方案?

#include <vector>
#include <set>
#include <algorithm>
#include <numeric>
#include <boost/random.hpp>

boost::random::mt19937 rng;

// Actually, f is a very complex function, that I'm not posting here.
double f(const std::vector<int>& perm) {
    boost::random::uniform_real_distribution<> gen;
    return gen(rng);
}

typedef std::pair<std::vector<int>, double> TValue;

void main(int argc, int args) {
    auto comp = [](const TValue& v1, const TValue& v2) { return v1.second < v2.second; };
    std::set<TValue, decltype(comp) > fPerm(comp);
    int n = 7;
    std::vector<int> perm(n);
    std::iota(perm.begin(), perm.end(),1);
    do {
        fPerm.insert(TValue(perm, f(perm)));
    } while (std::next_permutation(perm.begin(), perm.end()));

    // Get first smallest 100 values, if there are such many.
    int m = 100 < fPerm.size() ? 100 : fPerm.size();
    auto iterEnd = fPerm.begin();
    std::advance(iterEnd, m);
    for (auto iter = fPerm.begin(); iter != iterEnd; iter++) {
        std::cout << iter->second << std::endl;
    }
}

最佳答案

我修改了上面的解决方案,实现了一种删除集合中最大元素的修剪函数。正如下面所指出的,使用 std::priority_queue 可能会更短。

#include <vector>
#include <set>
#include <algorithm>
#include <numeric>
#include <boost/random.hpp>

boost::random::mt19937 rng;

double f(const std::vector<int>& perm) {
    boost::random::uniform_real_distribution<> gen;
    return gen(rng);
}

typedef std::pair<std::vector<int>, double> TValue;

void main(int argc, int args) {
    auto comp = [](const TValue& v1, const TValue& v2) { return v1.second < v2.second; };
    std::set<TValue, decltype(comp) > fPerm(comp);
    int n = 7;
    std::vector<int> perm(7);
    std::iota(perm.begin(), perm.end(),1);
    do {
        fPerm.insert(TValue(perm, f(perm)));
        if (fPerm.size() > 100) {
            fPerm.erase(*fPerm.rbegin());
        }
    } while (std::next_permutation(perm.begin(), perm.end()));

    // Get first smallest 100 values, if there are such many.
    int m = 100 < fPerm.size() ? 100 : fPerm.size();
    auto iterEnd = fPerm.begin();
    std::advance(iterEnd, m);
    for (auto iter = fPerm.begin(); iter != iterEnd; iter++) {
        std::cout << iter->second << std::endl;
    }
}

关于c++ - 更新 std::set 以仅保留最小值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38009312/

相关文章:

algorithm - 计算哪些字符串将具有相同的散列

c++ - 为什么按显式不可移动和隐式不可复制类型的值返回 vector 不会产生编译错误?

c++ - 使用带有 vector : 'std::vector' default constructor error 的自定义类

r - 如何将单词添加到语料库中的文档中?

algorithm - 当 f(n) = O(n!) 且 k=n*(n-1) 时 f(k) 的复杂度

c++ - 有或没有虚拟的子类与性能与便利性

c++ - 结构体中的指针问题

c++ - 高级函数指针?

c++ - 插入要设置的 vector 项

c++ - 任何代表有序元素对的 STL/boost 类型?