添加向量元素的所有排列

时间:2015-04-10 13:48:00

标签: c++

我有一个任意数量的向量:

vector<double> A1= (4.0, 9.5, 6.8)
vector<double> A2= (3.2, 2.1, 7.8,9.0)
vector<double> A3= (5.8, 9.1)
vector<double> A4= (5.4)
vector<double> A5= (5.6, 7.2);

现在我想以这样的方式添加这些向量A1,..,A5,以便生成所有排列并将它们添加到一起:

(4.0 + 3.2 + 5.8 + 5.4 + 5.6)
(4.0 + 3.2 + 5.8 + 5.4 + 7.2)
(4.0 + 3.2 + 9.1 + 5.4 + 5.6)
(4.0 + 3.2 + 9.1 + 5.4 + 7.2)
(4.0 + 2.1 + 5.8 + 5.4 + 5.6)
(4.0 + 2.1 + 5.8 + 5.4 + 7.2)
(4.0 + 2.1 + 9.1 + 5.4 + 5.6)
(4.0 + 2.1 + 9.1 + 5.4 + 7.2)
(4.0 + 7.8 + 5.8 + 5.4 + 5.6)
(4.0 + 7.8 + 5.8 + 5.4 + 7.2)
(4.0 + 7.8 + 9.1 + 5.4 + 5.6)
(4.0 + 7.8 + 9.1 + 5.4 + 7.2)
(4.0 + 9.0 + 5.8 + 5.4 + 5.6)
(4.0 + 9.0 + 5.8 + 5.4 + 7.2)
(4.0 + 9.0 + 9.1 + 5.4 + 5.6)
(4.0 + 9.0 + 9.1 + 5.4 + 7.2)

(9.5 + 3.2 + 5.8 + 5.4 + 5.6)
(9.5 + 3.2 + 5.8 + 5.4 + 7.2)
(9.5 + 3.2 + 9.1 + 5.4 + 5.6)
(9.5 + 3.2 + 9.1 + 5.4 + 7.2)
(9.5 + 2.1 + 5.8 + 5.4 + 5.6)
(9.5 + 2.1 + 5.8 + 5.4 + 7.2)
(9.5 + 2.1 + 9.1 + 5.4 + 5.6)
(9.5 + 2.1 + 9.1 + 5.4 + 7.2)
(9.5 + 7.8 + 5.8 + 5.4 + 5.6)
(9.5 + 7.8 + 5.8 + 5.4 + 7.2)
(9.5 + 7.8 + 9.1 + 5.4 + 5.6)
(9.5 + 7.8 + 9.1 + 5.4 + 7.2)
(9.5 + 9.0 + 5.8 + 5.4 + 5.6)
(9.5 + 9.0 + 5.8 + 5.4 + 7.2)
(9.5 + 9.0 + 9.1 + 5.4 + 5.6)
(9.5 + 9.0 + 9.1 + 5.4 + 7.2)

(6.8 + 3.2 + 5.8 + 5.4 + 5.6)
(6.8 + 3.2 + 5.8 + 5.4 + 7.2)
(6.8 + 3.2 + 9.1 + 5.4 + 5.6)
(6.8 + 3.2 + 9.1 + 5.4 + 7.2)
(6.8 + 2.1 + 5.8 + 5.4 + 5.6)
(6.8 + 2.1 + 5.8 + 5.4 + 7.2)
(6.8 + 2.1 + 9.1 + 5.4 + 5.6)
(6.8 + 2.1 + 9.1 + 5.4 + 7.2)
(6.8 + 7.8 + 5.8 + 5.4 + 5.6)
(6.8 + 7.8 + 5.8 + 5.4 + 7.2)
(6.8 + 7.8 + 9.1 + 5.4 + 5.6)
(6.8 + 7.8 + 9.1 + 5.4 + 7.2)
(6.8 + 9.0 + 5.8 + 5.4 + 5.6)
(6.8 + 9.0 + 5.8 + 5.4 + 7.2)
(6.8 + 9.0 + 9.1 + 5.4 + 5.6)
(6.8 + 9.0 + 9.1 + 5.4 + 7.2)

我尝试使用5 for循环将它们组合在一起但是当我有A1,... AN向量时,这种方法不起作用,因为我不能在代码中硬编码N for循环,其中'N'是用户定义的

5 个答案:

答案 0 :(得分:2)

使用递归调用这样的事情:

void calculate(int sum, size_t n, vector<vector<int>>& va)
{
    if (va.size() > n)
    {
        for (auto x : va[n])
        {
            calculate(sum+x, n+1, va);
        }
    }
    else
    {
        cout << sum << endl;
    }
}

int main()
{
    vector<vector<int>> all;
    vector<int> A1 = {1, 2};
    vector<int> A2 = {5, 10};
    all.push_back(A1);
    all.push_back(A2);
    calculate(0, 0, all);
    return 0;
}

答案 1 :(得分:1)

你能使用矢量矢量吗?然后尝试使用嵌套循环将它们基于向量向量的大小添加到一起,而不是每个向量的for循环。

编辑:如何做到:

vector double solutions; 
   for each inputVector
        oldSolution = solutions
        clear solutions
        for each element in an inputVector
            oldSolutionsCopy = oldSolution
            add the current element to every vector in solutions vector copy
            add oldSolutionsCopy to solutions

如果我通过正确的方式认为这会给出:

输入:

A = {0, 1, 2}
B = {b, c}
C = {y, z}

第一个循环给出: 溶液=

sum({0})
sum({1})
sum({2})

第二个循环给出:

sum({0}{a})
sum({1}{a})
sum({2}{a})
sum({0}{b})
sum({1}{b})
sum({2}{b})

第三循环给出:

sum({0}{a}{y})
sum({1}{a}{y})
sum({2}{a}{y})
sum({0}{b}{y})
sum({1}{b}{y})
sum({2}{b}{y})
sum({0}{a}{z})
sum({1}{a}{z})
sum({2}{a}{z})
sum({0}{b}{z})
sum({1}{b}{z})
sum({2}{b}{z})

它可能需要对边缘情况进行一些清理,这只是一个丑陋的sudo代码,但我认为它可以工作哈哈。

答案 2 :(得分:1)

首先,制作一个vector<vector<double>> A而不是A1,A2 ...... An。

对于实际任务,非常简单但不是很快的解决方案,
首先你需要一个vector<size_t> index 用A包含向量(即A.size())填充0 然后是这样的事情:

size_t i;
while(index[0] < A[0].size())
{
    //sum calculation
    double sum = 0.0;
    for(i = 0; i < A.size(); i++)
        sum += A[i][index[i]];
    cout << sum << endl; // or collect all sum´s in a vector, or...

    //index change / overflow detection
    i = A.size() - 1;
    index[i]++;
    while(index[i] >= A[i].size() && i > 0)
    {
        index[i] = 0;
        i--;
        index[i]++;
    }
}

递归/堆栈解决方案会更快。
后者与上面的代码没有什么不同,
只有在某个地方存储了一个中间数...

答案 3 :(得分:1)

也许我错过了一些东西,但它不会像将所有载体连接成一个载体那样容易:

std::vector<double> A_all;
A_all.insert(std::end(A_all), std::begin(A1), std::end(A1));
...
std::sort(std::begin(A_all), std::end(A_all));
if (A_all.size() >= 12)
{
    std::cout << "Are you sure?" << std::endl;
    std::exit(0);
}
std::vector<double> result;
do
{
    double sum = std::accumulate(std::begin(A_all), std::end(A_all), 0.0);
    result.push_back(sum); // should be almost the same for each entry
} while (std::next_permutation(std::begin(A_all), std::end(A_all));

参考文献:accumulatenext_permutationnumber of permutations

注意:我没有编译和测试此代码。

答案 4 :(得分:0)

这是一个简单的递归版本:

#include <vector>
#include <iostream>

using namespace std;

void gps(const vector< vector<double> >& data, size_t i=0, double s=0) {
    if (i == data.size()) // the index is past all vectors, (1)
        cout << s << endl;
    else
        // for each element of the current vector
        for (auto v : data[i])
            gps(data, i + 1, s + v);  // add the element to the sum
            // and do recursion for the next vector till we get to (1)
}

int main() {
    vector< vector<double> > data = { {4.0, 9.5, 6.8},
        {3.2, 2.1, 7.8, 9.0}, {5.8, 9.1}, {5.4}, {5.6, 7.2}};
    gps(data);
    return 0;
}

没有递归的版本:

#include <vector>
#include <iostream>

using namespace std;

void gps2(const vector< vector<double> >& data) {
    // calculate all possible permutations (multiply each vector length)
    size_t perms = 1;
    for (auto v : data)
        perms *= v.size();

    for (int i = 0; i < perms; ++i) {
        double s = 0; // initialize sum = 0
        size_t tmp = i;

        for (int j = data.size() - 1; j >= 0; --j) {
            size_t k = tmp % data[j].size(); // The reminder is the index
            tmp /= data[j].size(); // prepare for the next vector
            s += data[j][k]; // update the sum
        }
        cout << s << endl; // print the sum
    }
}

int main() {
    vector< vector<double> > data = { {4.0, 9.5, 6.8},
        {3.2, 2.1, 7.8, 9.0}, {5.8, 9.1}, {5.4}, {5.6, 7.2}};
    gps2(data);
    return 0;
}