簡體   English   中英

2D點的排列

[英]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_permutationfalse

由於您的命令說(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM