2D点的排列

时间:2013-10-15 12:05:33

标签: c++ c++11

我想探索二维点的所有排列(二维数组中的x,y坐标) 我的2点结构是:

struct pos_t {
    int x; int y; 
    pos_t(){x = 0 ; y = 0;} 
    pos_t(int X, int Y){x=X; y=Y;}
    pos_t(pos_t const & r) {x = r.x; y=r.y;}
    pos_t& operator=(pos_t const & r) {x = r.x; y=r.y; return *this;}
    bool operator < ( pos_t& p2)
    {
        return (x+y) < (p2.x+p2.y);
    }
    friend ostream& operator << (ostream &o, const pos_t& p)
    {
        return o << "(" << p.x << "," << p.y << ")";
    }
};

使用pos_t调用宝珀(vector<pos_t>)的向量,我使用下面的代码迭代其他不同的排列并显示每个。

    do {
        copy(begin(treasurePos), end(treasurePos), ostream_iterator<pos_t>(cout, " -> "));
        cout << endl;
    } while ( std::next_permutation(begin(treasurePos),end(treasurePos)) );

但是我的向量中有以下pos_t元素:(0,2)和(1,0) 我只得到一个排列:(0,2) -> (1,0) ->

我希望有:

(0,2) -> (1,0) -> 
(1,0) -> (0,2) -> 

另一个例子,有4个点,我只得到2个permutatin:

(1,3) -> (2,2) -> (3,0) -> (3,1) -> 
(1,3) -> (2,2) -> (3,1) -> (3,0) -> 

有你的想法吗?

5 个答案:

答案 0 :(得分:5)

next_permutationfalse时,新排列的字典顺序不是旧的排列。

由于您的排序表明(1,0)小于(0,2),因此序列{(1,0), (0,2)}的字典缩写小于{(0,2), (1,0)},而next_permutationfalse立刻。

同样的原因是你的四点例子。

如果您想要完成所有排列,则应首先对序列进行排序。

答案 1 :(得分:1)

在molbdnil上面回答。要获得所有排列,应对初始集进行排序。所以,这应该可以解决问题。

std::sort(begin(treasurePos), end(treasurePos));
do {
    copy(begin(treasurePos), end(treasurePos), ostream_iterator<pos_t>(cout, " -> "));
    cout << endl;
} while ( std::next_permutation(begin(treasurePos),end(treasurePos)) );

答案 2 :(得分:1)

最后我发现为什么即使拨打sort,我也永远不会得到所有的排列(请参阅我的回答......),但再次感谢您的帮助。

在拨打std::sort之前提及next_permutation的电话的所有答案都是正确的(这就是为什么我投票的大部分答案)。但事实上,最重要的是注意到lexicographic顺序取决于您使用的比较运算符。

默认参数是bool operator < ( ... )但是根据我提供的实现(见下文),(1,3)等于(3,1)。

bool operator < ( pos_t& p2)
{
    return (x+y) < (p2.x+p2.y);
}

这就是为什么我永远不会得到排列(即N 不同的元素,我们得到N!排列)

pos_t的正确操作员将是:

bool operator < ( pos_t const & p) const
{
  return (x < p.x) || ((x == p.x) && (y < p.y));
}

现在我们可以对所有排列进行排序,循环和收集。

std::sort(begin(treasurePos), end(treasurePos));
do {
  vector<pos_t> c;
  copy(begin(treasurePos), end(treasurePos), back_inserter(c));

  copy(begin(c), end(c), ostream_iterator<pos_t>(cout, " -> "));
  cout << endl;

  treasure_order.push_back(c);

} while ( std::next_permutation(begin(treasurePos),end(treasurePos)) );

cout << "we stored " << treasure_order.size() << " path to get all the treasure (=nbTreasure! = " << fact((int)treasurePos.size()) << ")" << endl;

答案 3 :(得分:0)

为了使std :: next_permutation能够给出所有排列,你的初始向量应该在循环之前用相同的比较器排序。

答案 4 :(得分:-1)

来自cplusplus.com

  

将[first,last]范围内的元素重新排列为下一个按字典顺序排列的更大排列。

     

可以根据他们如何比较词典相互比较来排序不同的排列;第一个这样排序的可能排列(将字典缩小与所有其他排列相比较的排列)是所有元素按升序排序的,而最大排列的所有元素按降序排序。

     

如果函数可以确定下一个更高的排列,它会重新排列元素并返回true。 如果那是不可能的(因为它已经处于最大可能的排列),它会根据第一个排列重新排列元素(按升序排序)并返回false。

所以基本上,如果你想让它起作用,那么起始排列必须是最小的。