【问题标题】:Update std::set to keep only the smallest values更新 std::set 以仅保留最小值
【发布时间】:2016-06-24 08:54:43
【问题描述】:

对于某些算法,我必须在 n-element 整数集的所有排列上调用函数 f 范围从 1 到 n。最后,我对产生最小f-value 的 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;
    }
}

【问题讨论】:

  • 为什么要保留所有排列?保留 100 个最小的解和相关的排列。如果找到一个新的最小解,则用它的排列替换其中一个最小的解。我会将解决方案保留在排序的出队中,将新解决方案添加到队列的下端,删除 sol
  • @GMichael 当你保留最小的 100 个并找到一个新的最小的时,你应该扔掉 100 个中最大的一个。
  • 感谢您的快速回复。其实,这就是我想做的。但是我将如何准确地做到这一点,以及什么是最好和最短的解决方案。
  • @arekolek 不,我会做一些更简单的事情。我会将它们保存在已排序的容器中,添加新的最小值并从保留的值中删除最大值。我还将使用保留的值作为将排列存储在另一个容器中的键。

标签: c++ algorithm stl permutation stdset


【解决方案1】:

我通过实现一种删除集合中最大元素的修剪功能来修改我的解决方案。正如下面所指出的,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;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    相关资源
    最近更新 更多