【问题标题】:Permutating a vector置换向量
【发布时间】:2014-04-17 17:35:59
【问题描述】:

我正在尝试获取向量的每个排列,但也尝试使用指示子排列的分隔符。从我的结果中您可以看到结束排列,我的代码似乎有错误。

0 1 3 2 |0 2 3 1 |0 3 2 1 | 都是重复的。

我也很好奇是否有一种方法可以做我想做的事情,可以接受对向量的引用而不是复制。

IDEONE:http://ideone.com/fork/2v0wk3

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

void permute(vector<int> v, int path_length) {
    do {
        for(int i=0; i<=3; ++i) {
            cout << v[i] << " ";
            if(i == path_length-1)
            cout << "| ";
        }
        cout << endl;

        if(path_length == v.size()) {
            cout << "====="<< endl;
            return;
        }

        permute(v, path_length+1);
    } while(next_permutation(v.begin()+path_length-1,v.end()));
}

int main() {
    vector<int> v;

    for(int i=0;i<=3;++i)
        v.push_back(i);

    int path_length = 2;
    permute(v, path_length);
    return 0;
}

结果:

0 1 | 2 3 
0 1 2 | 3 
0 1 2 3 | 
=====
0 1 3 | 2 
0 1 3 2 | 
=====
0 1 | 3 2 
0 1 3 | 2 
0 1 3 2 | 
=====
0 2 | 1 3 
0 2 1 | 3 
0 2 1 3 | 
=====
0 2 3 | 1 
0 2 3 1 | 
=====
0 2 | 3 1 
0 2 3 | 1 
0 2 3 1 | 
=====
0 3 | 1 2 
0 3 1 | 2 
0 3 1 2 | 
=====
0 3 2 | 1 
0 3 2 1 | 
=====
0 3 | 2 1 
0 3 2 | 1 
0 3 2 1 | 
=====

预期结果:

0 1 | 2 3 
0 1 2 | 3 
0 1 2 3 | 
=====
0 1 3 | 2 
0 1 3 2 | 
=====
0 2 | 1 3 
0 2 1 | 3 
0 2 1 3 | 
=====
0 2 3 | 1 
0 2 3 1 | 
=====
0 3 | 1 2 
0 3 1 | 2 
0 3 1 2 | 
=====
0 3 2 | 1 
0 3 2 1 | 
=====

【问题讨论】:

  • 所以基本上,你希望看到在你的 main() 函数中声明的向量“v”在 permute() 被调用后改变了值?或者更重要的是,您是否期望在递归调用 permute() 之后更改“v”参数?
  • 我更感兴趣的是为了对最优 TSP 问题进行分支定界算法而创建的排列。向量的 int 表示图中顶点的索引。分隔符演示解决方案中的顶点(左)和需要进行成本估算的顶点之间的划分。我的想法是如果 min-cost > lowerbound 我可以跳过排列
  • 您确定问题不在于您传递向量by value 而不是by reference?按值传递向量对我来说看起来很可疑。一旦 permute() 返回,所有 next_permutation() 所做的更改都会丢失。
  • 这是解决方案/问题的一部分,只是通过引用导致无限循环,所以这就是我遇到的问题。我希望它在第一次调用中通过引用传递,以便0 1 | 2 30 1 3 2 | 之后从0 2 | 1 3 开始,但在其他调用中我不希望通过引用传递它

标签: c++ algorithm vector permutation


【解决方案1】:

考虑另一种方法来生成您需要的每个序列。 我们将有一个vector &lt;int&gt; cur 来存储当前序列,以及一个vector &lt;bool&gt; used 来跟踪哪些整数被使用,哪些没有。 在带有depth 参数的递归函数中,找到另一个未使用的整数,将其作为cur[depth] 并继续考虑下一个位置,即depth + 1。 只要深度在要求的范围内,就打印结果。

#include <iostream>
#include <vector>
using namespace std;

int const n = 3;

void generate (vector <int> & cur, vector <bool> & used, int depth) {
    if (depth >= 2) {
        for (int i = 0; i < depth; i++) {
            cout << cur[i] << ' ';
        }
        cout << endl;
    }
    for (int i = 0; i <= n; i++) {
        if (!used[i]) {
            used[i] = true;
            cur[depth] = i;
            generate (cur, used, depth + 1);
            used[i] = false;
        }
    }
}

int main () {
    vector <int> cur (n);
    vector <bool> used (n, false);
    cur[0] = 0;
    used[0] = true;
    generate (cur, used, 1);
    return 0;
}

输出是:

0 1 
0 1 2 
0 1 2 3 
0 1 3 
0 1 3 2 
0 2 
0 2 1 
0 2 1 3 
0 2 3 
0 2 3 1 
0 3 
0 3 1 
0 3 1 2 
0 3 2 
0 3 2 1 

如果您在depth &gt; n 时打印,您也可以添加===== 部分。

【讨论】:

  • 不完全是我想要的,但足够接近我可以使用。我需要我的分隔符的剩余值。
  • @BHare:如果您不需要考虑它们的顺序,可以通过遍历 used 数组并查看哪些未使用来恢复它们。
【解决方案2】:

你的问题对我来说不是很清楚。您可以使用 STL 中不太知名的next permutation

std::vector<int> my_vector = { 1 , 5 , 7 , 2 , 3 , 10};
std::sort(my_vector.begin(), my_vector.end());
do {
    std::copy(my_vector.begin(), my_vector.end(), ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
} while(std::next_permutation(my_vector.begin(), my_vector.end()));

1 - 对向量进行排序 2 - 迭代排列 (do while 只需将其打印到 cout 即可)

我不知道你所谓的“子”排列,你只是移动“|”在每个排列里面?

【讨论】:

  • 请注意,(1) 问题 does 中的代码使用 next_permutation 和 (2) 所需的输出不同于所有排列。相反,它是 {1,2,3} 的所有有序集合,前面加 0。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
  • 2011-03-12
  • 2021-10-05
  • 2012-11-06
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多