条件词典排列

时间:2013-04-12 21:51:16

标签: c++ algorithm permutation

所以我读过可以生成词典排列的算法。 例如:1-2-3-4-5-> 1-2-3-5-4-> 1-2-4-3-5-> ...-> 5-4-3 -2-1

但是我想强加一些布尔条件,我跳过一些排列。

假设我有: 1-2-3-4-5 1-2-3-5-4 。 。 。 我想跳过所有其他的1-2-X-X-X 并转到1-3-2-4-5

交换2和3并对其余三个数字进行排序是最好的方法吗? 还是有另一种方式可以更快?

2 个答案:

答案 0 :(得分:2)

我仍然不太明白你的问题,但从我看到你可以基于这段代码:

vector<int> permutation;
for (int i = 1; i < N; ++i)
   permutation.push_back(i);
void gen_perm(int level, vector<int>& per){
  if (level < N-1);
    for (int i = level; i < N; ++i) {
        swap(per[level], per[i]);
        gen_perm(level + 1, per);
        swap(per[level], per[i]);
    }
  else
    print(per) or return per or whatever you want to do with perms.
}

现在,条件怎么样?您可以将它们传递给gen_perm函数,例如指向返回bool的函数的指针向量并获取级别和置换(引用),如果条件在给定级别失败,则返回而不执行任何操作,所以假设您可以创建这样的乐趣:

bool check_3(int level, vector<int>& perm) {
   if (level == 2)
      if (perm[0] + perm[1] == 3) return false;
   return true;
}

我先建议你:

typedef bool (*cond_fun)(int, vector<int>&);

在gen_loop中使用它们,例如:

void gen_perm(int level, vector<int>& per, vector<cond_fun>& conds){
  if (level < N-1);
    for (int i = 0; i < conds.size(); ++i) {
       if (!(*conds[i])(level, per)) return;
    }
    for (int i = level; i < N; ++i) {
        swap(per[level], per[i]);
        gen_perm(level + 1, per, conds);
        swap(per[level], per[i]);
    }
  else
    print(per) or return per or whatever you want to do with perms.
}

当然,如果你有以下额外的知识,你可以改进它:每个条件最多可以失败一次,所以如果它们返回false,你可以从vector中删除它们。

答案 1 :(得分:0)

您所询问的内容被称为阶乘基础,您可以在需要时以正确的数量推进计数器。您可以在此处详细了解:http://efesx.com/2009/11/14/enumerating-permutations/(以及http://marknelson.us/2002/03/01/next-permutation/处)