【问题标题】:Algorithm loop combination算法循环组合
【发布时间】:2016-08-14 08:33:08
【问题描述】:

我有 10 个文本文件,其中包含一列 1,-1,0。 我想设置一个组合来总结每个文件的元素。

例如,如果我想查看 10 个文件中 2 个文件的所有组合,我将创建以下 2 个循环: 双倍总和;

for(int i;i=0;i<n;i++){
    for(int j;j=i;j<n;j++){
        sum += x[i]+x[j];
    }
}

另一个例子,如果我想查看 10 个文件中 3 个文件的所有组合,我会创建下面的 3 个循环:

for(int i;i=0;i<n;i++){
    for(int j;j=i;j<n;j++){
        for(int k;k=j;k<n;k++)
           sum += x[i]+x[j]+x[k];
        }
    }
}

以此类推,如果我想查看 10 个文件中的 x 个文件的组合,我会创建 x 个循环。

我的问题是:我正在寻找一种通过选择 x 来确定循环数的算法。如果 x=2,那么我创建 2 个循环,如果 x=3,那么我创建 3 个循环,如果 x=4,那么我创建 4 个循环,......或者可能有另一种方式。 非常感谢

【问题讨论】:

  • 如果你有 50 个文件,50 个嵌套循环?这太疯狂了。不用说,有更好的方法,例如使用std::next_permutation 以及一些逻辑来生成组合(SO上有许多示例),您需要一个(或两个)循环,无论项目数。
  • @PaulMcKenzie std::next_permutation 在这里看起来不是很有用,因为 TS 需要组合,而不是排列
  • @alexeykuzmin0 -- 你错了。如果您输入some effort into it.,则可以使用std::next_permutation 生成组合。诀窍是使用由布尔值组成的控制数组。

标签: c++ loops combinations


【解决方案1】:

我不确定您提供的代码是否真的像for (int i;i=0;i&lt;n;++i) 一样工作,很可能必须是for (int i=0;i&lt;n;++i)。尽管如此,您正在寻找某种递归。

假设您已将此数据存储在 std::vector 中,我建议您创建一个 2D 变体 std::vector&lt;std::vector&lt;int&gt;&gt;

递归需要两个元素:停止条件和递归:

void function(int &sum, const std::vector<std::vector<int>> &data, std::size_t outerLevel, std::size_t innerLevel, int intermediate) {
    // Stop condition of recursion,
    // if we don't have any elements any more,
    // the intermediate is our final result.
    if (outerLevel == data.size()) {
        sum += intermediate;
        return;
    }

    // Recursing
    const std::vector<int> &subData = data[outerLevel];
    for (auto i = innerLevel; i < subData.size(); ++i) {
        function(sum,
                 data,
                 outerLevel+1, // Go to the next std::vector<int>
                 i,            // Make sure the next inner loop starts at the right index
                 intermedite+subData[i] // Take the intermidiate sum
                 );
    }
}

// Wrapper to hide itermediate calculation variables
int functionWrapper(const std::vector<std::vector<int>> &data) {
    int sum = 0;
    function(sum, data, 0, 0, 0);
    return sum;
}

【讨论】:

    【解决方案2】:

    如果你只是想计算总和,它甚至很简单

    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            sum += x[i] + x[j];
        }
    }
    

    等价于

    for (int i = 0; i < n; i++) {
        sum += (n - i) * x[i];
        for (int j = i; j < n; j++) {
            sum += x[j];
        }
    }
    

    还有更多的努力

    sum += (n + 1) * std::accumulate(std::begin(x), std::end(x), 0);
    

    对于 3

    const int sumx = std::accumulate(std::begin(x), std::end(x), 0);
    sum += ((n + 1) * (n + 2) / 2) * sumx;
    

    【讨论】:

    • 我要感谢所有这么快回答我的问题的人。我会研究答案,如果我理解了,我会带着代码回来。我不得不说我需要花一些时间来确保我理解算法。首先,我将学习 PaulMcKenzie
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    • 2011-07-18
    • 1970-01-01
    相关资源
    最近更新 更多