【问题标题】:signature next_permutation c++签名 next_permutation c++
【发布时间】:2017-05-12 01:28:37
【问题描述】:

我想知道是否有一种简单的方法可以从 c++ 的std::next_permutation 创建的排列顺序中了解它们的排列的parity(签名)。

int main()
{
    int counter = 0;
    std::vector<int> mask {0, 1, 2, 3, 4};
    do 
    {
        counter++;
        // then determine the parity of permutation from knowledge of the counter
    } while (std::next_permutation(mask.begin(), mask.end()));
}

或者,是否有内置函数来确定排列的奇偶性?

【问题讨论】:

标签: c++ std permutation


【解决方案1】:

编辑:下面的规则是错误的。我正在尝试修复它。

这里似乎有一个不错的组合奇迹!如果您按字典顺序枚举排列(因为它由 C++ 标准指定,请参见例如:http://en.cppreference.com/w/cpp/algorithm/next_permutation),那么一些实验似乎表明该符号遵循以下规则: 从一个开始,然后更改符号,然后每隔一个排列更改符号。

[1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1 ...]

我目前不明白为什么,但我检查了这是真实的,最大尺寸为 ***。这里以 n=4 为例:

 ([1, 2, 3, 4], 1)
 ([1, 2, 4, 3], -1)
 ([1, 3, 2, 4], -1)
 ([1, 3, 4, 2], 1)
 ([1, 4, 2, 3], 1)
 ([1, 4, 3, 2], -1)
 ([2, 1, 3, 4], -1)
 ([2, 1, 4, 3], 1)
 ([2, 3, 1, 4], 1)
 ([2, 3, 4, 1], -1)
 ([2, 4, 1, 3], -1)
 ([2, 4, 3, 1], 1)
 ([3, 1, 2, 4], 1)
 ([3, 1, 4, 2], -1)
 ([3, 2, 1, 4], -1)
 ([3, 2, 4, 1], 1)
 ([3, 4, 1, 2], 1)
 ([3, 4, 2, 1], -1)
 ([4, 1, 2, 3], -1)
 ([4, 1, 3, 2], 1)
 ([4, 2, 1, 3], 1)
 ([4, 2, 3, 1], -1)
 ([4, 3, 1, 2], -1)
 ([4, 3, 2, 1], 1)

我认为这回答了你的问题。我会尽快找到解释的。

【讨论】:

    【解决方案2】:

    我认为没有这样的现有功能,但您可以使用仪器实现自己的next_permutation。比如:

    enum class Parity {Even, Odd};
    
    Parity operator+ (Parity parity, std::size_t count)
    {
        return static_cast<Parity>((static_cast<std::size_t>(parity) + count) % 2);
    }
    
    template<typename It>
    bool next_permutation(It begin, It end, Parity& parity)
    {
        if (begin == end)
            return false;
    
        It i = begin;
        ++i;
        if (i == end)
            return false;
    
        i = end;
        --i;
    
        while (true)
        {
            It j = i;
            --i;
    
            if (*i < *j)
            {
                It k = end;
    
                while (!(*i < *--k))
                    /* pass */;
    
                std::iter_swap(i, k);
                parity = parity + 1;
                std::reverse(j, end);
                parity = parity + std::distance(j, end) / 2;
                return true;
            }
    
            if (i == begin)
            {
                std::reverse(begin, end);
                parity = parity + std::distance(begin, end) / 2;
                return false;
            }
        }
    }
    

    Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-02
      • 1970-01-01
      • 2016-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多