我想探索二维点的所有排列(二维数组中的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) ->
有你的想法吗?
答案 0 :(得分:5)
next_permutation
为false
时,新排列的字典顺序不是旧的排列。
由于您的排序表明(1,0)
小于(0,2)
,因此序列{(1,0), (0,2)}
的字典缩写小于{(0,2), (1,0)}
,而next_permutation
为false
立刻。
同样的原因是你的四点例子。
如果您想要完成所有排列,则应首先对序列进行排序。
答案 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)
将[first,last]范围内的元素重新排列为下一个按字典顺序排列的更大排列。
可以根据他们如何比较词典相互比较来排序不同的排列;第一个这样排序的可能排列(将字典缩小与所有其他排列相比较的排列)是所有元素按升序排序的,而最大排列的所有元素按降序排序。
如果函数可以确定下一个更高的排列,它会重新排列元素并返回true。 如果那是不可能的(因为它已经处于最大可能的排列),它会根据第一个排列重新排列元素(按升序排序)并返回false。
所以基本上,如果你想让它起作用,那么起始排列必须是最小的。