大多数平衡的分区的排列

时间:2017-06-27 13:26:28

标签: algorithm math bit-manipulation heuristics

我正在研究树搜索算法,其中我使用通过位集表示的元素的二元组,即位集1000101表示二元{0,2,6} {1,3,4,5}

目前,我只是通过递增一个位集迭代所有的二分法,即迭代集合{0,1,2,3}的所有二分区,我从0001(包括)转到1000 (不包括)

由于我的算法有时会让我在找到合适的分区时“快速失败”,我想重新排序它们,以便我先看看更平衡的分区。

因此,我想询问是否有人知道从1到2 ^ k的数字的排列,其中min(#set bits,#unitset)或多或少只会减少,仍然可以有效地计算

由于这是一种启发式方法,我不是在寻找确切的结果,只是一种加快算法速度的方法。

1 个答案:

答案 0 :(得分:2)

罗里的评论让我朝着正确的方向前进:

如果我们从bitset中的固定数量的一开始,我们可以使用一些比特麻烦的黑客来简单地迭代所有这些。

  • 首先从0...01...1开始使用k/2,然后使用k/2 - 1k/2 - 2依此类推。

  • 对于每个起始值,使用Gosper's Hack迭代所有可能的位集排列,直到我们到达bitset的边界。

一个简单的实现可能如下所示(对于k <= 63

for (int i = k / 2; i > 0; --i) {
    // start with 0 ... 0 1 ... 1 (i times)
    unsigned int v = (1 << i) - 1;
    // first bitset that doesn't represent a valid bipartition
    unsigned int end = 1 << k;
    // without this, we would count some bipartitions twice for k even
    if (k % 2 == 0 && i == k / 2) end >>= 1;
    while(v < end) {
        // do something with v...
        // iterate to the lexicographically next permutation
        unsigned int t = v | (v - 1);
        v = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
    }
}