求乙個排列的下乙個排列我們有暴力的n進制法,當然也就有效率較高的字典序法。
洛谷1088 火星人
題目描述
求排列a[1],a[2],a[3],……,a[n]之後的第m個全排列。
輸入格式
共三行。
第一行乙個正整數n(1 <= n <= 10000)。
第二行乙個正整數m(1 <= n <= 100)。
下一行是1到n這n個整數的乙個排列,用空格隔開。
輸出格式
n個整數,表示第m個全排列。每兩個相鄰的數中間用乙個空格分開。
輸入輸出樣例
輸入
5
31 2 3 4 5
輸出
1 2 4 5 3
在原排列中從後往前找,找到第乙個比它後面數小的數,既找到第乙個a[pos]滿足a[pos] < a[pos + 1],簡而言之就是找到原排列的最長單調遞減的字尾的前乙個樹。
在原排列的最長單調遞減的字尾中從前往後找到最後乙個大於a[pos]的數a[k]。
調換a[pos]和a[k]。
對a[pos+1]……a[n]進行轉置,此時的排列就是原排列的下乙個排列。
這裡舉個例子:如排列986375421,我們發現原排列的最長單調遞減的字尾是75421,而75421前面的第乙個數就是3,而這個數3也就是我們再找的a[pos]。之後在排列75421中從前往後找到最後乙個大於3的數,既是4,這裡我們可以用到二分查詢upper_bound函式找到第乙個小於3的數的位置,之後將位置減一就是k了。接著調換3和4,序列變為986475321,最後再將75321轉置成12357,則我們就求出了排列986375421的下乙個全排列為986412357。
還有,記得加乙個特判:如果說當前排列整體就是單調遞減的,那麼這也就是最後乙個排列了,直接跳出就ok了,既pos = 0時返回false。
# include # include # include # include using namespace std;
const int n_max = 10000;
int n, m;
int a[n_max + 10];
bool cmp(int x, int y)
bool permutation()
int main()
演算法 全排列問題 字典中介法
有時我們希望可以找到乙個全排列的下m個全排列,而不僅僅是下乙個,就這樣出現了字典中介法。洛谷1088 火星人 題目描述 求排列a 1 a 2 a 3 a n 之後的第m個全排列。輸入格式 共三行。第一行乙個正整數n 1 n 10000 第二行乙個正整數m 1 n 100 下一行是1到n這n個整數的乙...
全排列演算法之字典序法
字典序演算法如下 設p是1 n的乙個全排列 p p1p2.pn p1p2.pj 1pjpj 1.pk 1pkpk 1.pn 1 從排列的右端開始,找出第乙個比右邊數字小的數字的序號j j從左端開始計算 即 j max index return index 在pj的右邊的數字中,找出所有比pj大的數中...
全排列之字典序法
1 對於輸入的字典序排列,反向查詢第一對滿足a j 2 仍舊反向查詢第乙個下標k,使得 a j 3 交換a j 和a k 4 翻轉a j 1 a end 此法能適應有重複元素的系列 如下 include include using namespace std int cmp const void a...