[英]Permutations of 2D points
我想探索2d點的所有排列(2D數組中的x,y坐標),我的2d點結構是:
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個置換素:
(1,3) -> (2,2) -> (3,0) -> (3,1) ->
(1,3) -> (2,2) -> (3,1) -> (3,0) ->
你有主意嗎?
當新排列在字典上不比舊排列大時, next_permutation
為false
。
由於您的命令說(1,0)
小於(0,2)
,因此序列{(1,0), (0,2)}
在字典上小於{(0,2), (1,0)}
, next_permutation
立即為false
。
同樣的原因也出現在您的四點示例之后。
如果要遍歷所有排列,則應首先對序列進行排序。
在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)) );
最終,我發現為什么即使調用sort
,也永遠無法獲得所有排列(請參閱我的回答...),但是再次感謝您的幫助。
在任何對next_permutation
調用之前,所有提及對std::sort
的調用的答案都是正確的(這就是為什么我對大多數答案都投了贊成票)。 但是實際上,最重要的是要注意, 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;
為了使std :: next_permutation能夠提供所有排列,您的初始向量應在循環之前使用相同的比較器進行排序。
來自cplusplus.com :
將[first,last)范圍內的元素重新排列到下一個字典上更大的排列。
可以根據它們在字典上的比較方式來排列不同的排列。 第一個這樣排序的可能排列(在字典上比較所有其他排列的排列)是將所有元素按升序排列的,而將最大元素按降序排列的排列。
如果函數可以確定下一個更高的排列 ,則它會按原樣重新排列元素並返回true。 如果這是不可能的(因為它已經處於最大可能的排列),則它將根據第一個排列(按升序排列)重新排列元素,並返回false。
因此,基本上,如果要使其工作,則起始排列必須是最小的排列。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.