问题描述
所以我知道有很多计算唯一排列的方法。 通常,在生成过程中应用限制要比事后删除限制要慢。 假设我有10个元素的向量。 举个例子:
std::vector<int> v = {7,5,16,8,1,7,3,25,109,8};
我有一个独特的限制,我知道我不允许连续使用相同的三个数字,因此任何地方包含{8,8}的所有排列都是无效的。 如果我有很多例如我假设20个元素,如果我跳过以{8,8}开头的所有排列,可以节省很多时间。
有什么办法可以有效地做这样的事情吗?我如何确定在什么时候增加检查每个排列的额外速度才有意义?
解决方法
在您的限制下,可以按顺序进行迭代,但是可以从第一个无效排列中跳过无效排列的块。
第一个无效排列形式
y y y 8 8 x x 8 x
是
因此您可以直接使用 所以只需倒数最后一个数字即可。y y y 8 8 8 x1 x2 x3
,x1 y y y 8 8 8 x3 x2 x1
,x1 bool is_valid(const std::vector<int>& v)
{
auto it = std::find(v.begin(),v.end(),8);
return v.end() - it >= 3 && (*it != *(it + 1) || *it != *(it + 2));
}
void go_to_last_invalid(std::vector<int>& v)
{
auto it = std::find(v.begin(),8);
std::reverse(it + 3,v.end());
}
int main()
{
std::vector<int> v = {1,7,8,9,10};
do {
if (!is_valid(v)) { go_to_last_invalid(v); continue; }
for (auto e : v) { std::cout << e << " "; } std::cout << std::endl;
} while (std::next_permutation(v.begin(),v.end()));
}