给定节点{1,2,...,N}
的子集,是否有任何STL
或boost
函数在所有节点上返回唯一的无向旅程?std::next_permutation()
给出所有N!
指导的游览,其中1-2-...-N
与N-N-1-...-2-1
不同。
但是,在这种情况下,我不希望它们两者都只需要其中之一。本质上,我只想列举旅行团的N! / 2
。
以下使用std::next_permutation()
和unordered_set
的代码有效,但是还有效率更高的方法吗?以下代码从本质上生成了所有N!
指示的巡视,并在检查了unordered_set()
之后丢弃了其中的一半。
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <boost/functional/hash.hpp>
template <typename T, typename U> bool unorderedset_val_there_already_add_if_not(std::unordered_set<T, U>& uos, T& val) {
if (uos.find(val) != uos.end())
return true;//val already there
uos.insert(val);
return false;//Value is new.
}
int main() {
std::vector<int> sequence{ 1, 2, 3};
std::unordered_set<std::vector<int>, boost::hash<std::vector<int>>> uos;
do {
printf("Considering ");
for (std::size_t i = 0; i < sequence.size(); i++)
printf("%d ", sequence[i]);
printf("\n");
std::vector<int> rev_sequence = sequence;
std::reverse(rev_sequence.begin(), rev_sequence.end());
if (unorderedset_val_there_already_add_if_not(uos, sequence) || unorderedset_val_there_already_add_if_not(uos, rev_sequence)) {
printf("Already there by itself or its reverse.\n");
}
else {
printf("Sequence and its reverse are new.\n");
}
} while (std::next_permutation(sequence.begin(), sequence.end()));
getchar();
}
也就是说,给定{1,2,3}
,我只想枚举(1-2-3)
,(1-3-2)
和(2-1-3)
。其他三个排列(2-3-1)
,(3-1-2)
和(3-2-1)
不应枚举,因为它们的反向顺序已经被枚举。
最佳答案
如果您想保留next_permutation
而不是使用自己的生成器例程,最简单的方法是在某些条件下过滤掉一半排列。
很简单:最后一个元素应该大于第一个元素。
#include <vector>
#include <algorithm>
#include "stdio.h"
int main() {
std::vector<int> sequence{ 1, 2, 3, 4};
do {
if (sequence[sequence.size()-1] > sequence[0]) {
for (std::size_t i = 0; i < sequence.size(); i++)
printf("%d ", sequence[i]);
printf("\n");
}
} while (std::next_permutation(sequence.begin(), sequence.end()));
getchar();
}
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 4 1 3
3 1 2 4
3 2 1 4
可能自己的实现:Generate all pairs (start; end) where start < end
Generate all permutations of `n-2` values without start and end
For every permutation make {start, permutation.., end}
1 ... 2 + permutations of {3, 4}
1 3 4 2
1 4 3 2
1 ... 3 + permutations of {2,4}
1 2 4 3
1 4 2 3
...
3 ... 4 + permutations of {1, 2}
3 1 2 4
3 2 1 4
...
关于c++ - 枚举唯一的无向路径的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63445072/