C++ 如何避免c++;?

C++ 如何避免c++;?,c++,for-loop,C++,For Loop,我需要编程所有可能的数字集,从1到N,用于无排列的任意整数m 因为我不知道如何更好地解释,这里有一些例子: 对于m=2 vector<vector<int>> box; int N = 5; for(int i = 1; i <= N; i++) { for(int j = N; j >= i; j--) { vector<int> dummy; dummy.push_back(i);

我需要编程所有可能的数字集,从
1
N
,用于无排列的任意整数
m

因为我不知道如何更好地解释,这里有一些例子:

对于
m=2

vector<vector<int>> box;    
int N = 5;

for(int i = 1; i <= N; i++) {
    for(int j = N; j >= i; j--) {
        vector<int> dummy;
        dummy.push_back(i);
        dummy.push_back(j);
        box.push_back(dummy);
    }
}
这工作非常好,结果就是我所需要的。但正如前面提到的,
m
可以是任意的,我不想费心为
m=37
或其他任何东西实现它
N
m
是已知值,但在程序运行时会发生变化。必须有比
m=37
案例更好的实现方法来实现37行for循环。有人能帮我吗?我有点不知所措:\

编辑:为了更好地解释我在寻找什么,这里还有一些例子

假设
N=5
m=4
,那么
1223
对我来说是一个可行的解决方案,
124
不是,因为它很短。假设我已经找到了
1223
作为解决方案,那么我就不需要
2123
2213
或这个数字的任何其他排列

编辑2:或者如果你喜欢一个更直观(数学?)的问题公式,那就来吧


考虑
m
维度。使用
m
2,您将得到
N
大小矩阵。我正在寻找这个矩阵的上(或下)三角形,包括对角线。让我们移动到
m=3
,矩阵变成一个三维立方体(或者张量,如果你愿意的话),现在我在寻找上(或者下)四面体,包括对角线平面。对于大于3的维度,我正在寻找超立方体的超四面体,包括超对角线平面。

可以使用递归查找所有子集。这可能在风格上有所改进,但下面是一个快速解决问题的方法:

std::vector<std::set<int>> subsets(std::vector<int> x)
{
    if (x.size() == 0)
        return { std::set<int>() };
    else
    {
        int last = x.back();
        x.pop_back();

        auto sets = subsets(x);
        size_t n = sets.size();

        for (size_t i = 0; i < n; i++)
        {
            std::set<int> s = sets[i];
            s.insert(last);
            sets.push_back(std::move(s));
        }

        return sets;
    }
}
std::vector子集(std::vector x)
{
如果(x.size()==0)
返回{std::set()};
其他的
{
int last=x.back();
x、 向后弹出();
自动设置=子集(x);
size_t n=sets.size();
对于(大小i=0;i
这将使每个递归步骤的答案数量增加一倍:子集的数量为2^n,正如预期的那样

如果愿意,可以用
std::set
替换
std::vector

以下通用算法允许客户每次访问长度为N,r项序列的每个组合或置换

用法示例:

std::vector<std::vector<int>> box;  

std::vector<int> v(N);
std::iota(begin(v), end(v), 1);

for_each_combination(begin(v), begin(v) + M, end(v), [](auto b, auto e) {
    box.emplace_back(b, e);
    return false;
});
维基百科很好地说明了这一点:它获取数字[0,N+M-1]的所有组合(不重复),然后查找结果中的“间隙”。间隙表示从一个元素的重复到下一个元素的重复的过渡

你传递给这个算法的函子是一个包含索引的范围,该索引进入一个包含你正在组合的元素的集合。例如,如果你想从{x,y}集合中得到三个元素的所有集合,结果是{x,x,x},{x,x,y},{x,y,y},{y,y,y},这个算法通过将索引范围返回到(有序)集合{x,y}:{{0,0,0},{0,0,1},{0,1,1},{1,1,1}来表示这一点

因此,通常要使用它,你有一个向量或包含元素的东西,并使用该算法生成的范围作为该容器的索引。然而,在你的情况下,由于元素只是从1到N的数字,你可以通过向每个索引添加一个来直接使用索引:

for_each_combination_with_repetition(N, M, [&](auto b, auto e) {
    for(; b != e; ++b) {
        int index = *b;
        std::cout << index + 1 << " ";
    }
    std::cout << '\n';
});
对于每个重复的组合(N,M,[&](自动b,自动e){
对于(;b!=e;++b){
int指数=*b;

std::不久前是否也有同样的问题,也许我会发现……这更适合于“无置换”的可能重复,你的意思是相同集合的不同置换被视为不同集合吗?在这种情况下,更好的术语可能是“从(包括)范围
[1,N]
中提取的
m
数字的所有可能的有序序列”。使用“无置换”我的意思是,如果我已经找到115,我不想找到151或511。我不太确定返回什么{std::set()};dose,但这不能为我编译。@solid:它用一个空集初始化返回向量。你使用的是古老的编译器吗?@solid它可能在std::vector上中断,它应该在右尖括号之间有一个空格:std::vector@solid:您可以将其替换为
std::vector(1)
(如果您的编译器太旧,请注意空格)。我正在使用VisualStudio2012,它在第一个返回行中抛出错误C2059:Syntaxfehler:“{”带空格和不带空格根据链接的输出不会给我122作为解决方案(我需要).但是如果我已经找到了122,我不想要122的排列,所以我不想要212或221。@solid啊,我明白了;而不是组合,你想要的是重复组合。链接库不包含此功能,但算法可以构建在
的基础上,对于每个组合
@solid,我添加了一个实现基于每个组合()的
重复组合的排序
template<typename Func>
void for_each_combination_with_repetition(int categories, int slots, Func func) {
    std::vector<int> v(slots + categories - 1);
    std::iota(begin(v), end(v), 1);

    std::vector<int> indices;
    for_each_combination(begin(v), begin(v) + slots, end(v), [&](auto b, auto e) {
        indices.clear();
        int last = 0;
        int current_element = 0;

        for(;b != e; ++last) {
            if (*b == last+1) {
                indices.push_back(current_element);
                ++b;
            } else {
                ++current_element;
            }
        }
        func(begin(indices), end(indices));
        return false;
    });
}
for_each_combination_with_repetition(N, M, [&](auto b, auto e) {
    for(; b != e; ++b) {
        int index = *b;
        std::cout << index + 1 << " ";
    }
    std::cout << '\n';
});
template<typename Func>
void for_each_combination_with_repetition(int categories, int slots, Func func) {
    std::vector<int> v(slots + categories - 1);
    std::iota(begin(v), end(v), 1);

    std::vector<int> repetitions(categories);
    for_each_combination(begin(v), begin(v) + slots, end(v), [&](auto b, auto e) {
        std::fill(begin(repetitions), end(repetitions), 0);

        int last = 0;
        int current_element = 0;

        for(;b != e; ++last) {
            if (*b == last+1) {
                ++repetitions[current_element];
                ++b;
            } else {
                ++current_element;
            }
        }
        func(begin(repetitions), end(repetitions));
        return false;
    });
}