鄰位互換法,只要你在學全排列就不可不學的乙個及其有趣的演算法。
洛谷1706 全排列問題
題目描述
按照鄰位互換法的順序輸出自然數1到n所有不重複的排列,即n的全排列,要求所產生的任一數字序列中不允許出現重複的數字。
輸入格式
乙個整數n。
輸出格式
由1~n組成的所有不重複的數字序列,每行乙個序列。
每個數字保留 5個場寬。
輸入樣例
3
輸出樣例
鄰位互換法其實是乙個比較容易理解的演算法,這裡我們需要定義乙個概念:如果說乙個數比它指標所指向的數小,它就處於活動狀態,當然所指向的數不能越界。此時,你可能會問這個指標是啥,其實這個指標只能指向他的下乙個數或者上乙個數,比如a[i]的指標只能指向a[i - 1]或者a[i + 1]。這個指標我們就用face[i]來記錄:當face[i] = 1時,表示a[i]指向a[i + 1];當face[i] = -1時,表示a[i]指向a[i - 1]。這樣使用起來也很方便,比如我要去找a[i]的指向位置,直接就是a[i + face[i]],不用再去if判斷了。1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
引入這個概念之後,我們就具體來說步驟了:
初始化全排列1, 2, 3,…… ,n。
將指標都指向左側,即face[i] = -1。
從a[1] ~ a[n]中找出處於活動狀態的最大值的位置pos。
如果沒有乙個處於活動狀態的數,代表所有的全排列已經生成完畢。
交換a[pos]和其指向的數a[pos_to]。pos_to就是a[pos]指向的位置,即pos + face[pos]。
交換face[pos]和face[pos_to]。這步千萬不要忘!
在排列中將所有的大於a[pos_to]的數的face都取反。這裡一定時a[pos_to]因為我們已經交換了a[pos]和a[pos_to]。
不停地迴圈重複步驟3、4、5、6、7,每次執行完一次就進行輸出,直到4步驟返回false,結束。
# include # include # include # include using namespace std;
const int n_max = 10;
int n;
int a[n_max + 10];
int face[n_max + 10];
bool canmove(int x)
bool permutation()
if (pos == -1) return false;
int pos_to = pos + face[pos];
swap(a[pos], a[pos_to]);
swap(face[pos], face[pos_to]);
for (int i = 1; i <= n; i++)
if (a[i] > a_max) face[i] = -face[i];
return true;
}int main()
while (permutation());
return 0;
}
全排演算法 JAVA
花了一中午終於理解了!第一種情況 1 2 3 4 無重複字元 每次固定第乙個 然後剩餘的在進行全排 1 234 2 134 3 214 4 231 接下來 234重排 2 34 3 24 4 32 其他都一樣了 直接上 public class main else private static ch...
演算法 錯排問題
錯排問題 就是一種遞推式,不過它比較著名且常用,所以要熟記!方法一 n各有序的元素應有n!種不同的排列。如若乙個排列式的所有的元素都不在原來的位置上,則稱這個排列為錯排。任給乙個n,求出1,2,n的錯排個數dn共有多少個。遞迴關係式為 d n n 1 d n 1 d n 2 d 1 0,d 2 1 ...
演算法 錯排問題
今天我們再來學習乙個比較簡單的演算法,今天我們學習的是錯排問題,什麼是錯排問題呢?這樣說吧,假如現在書架上放有10本書,每本書都有固定的位置,現在讓你重新排列這些書,讓新排好的每一本書都不在原來的位置問你有多少種排列的情況。假如我們用num陣列來代表可能的情況,那麼我們容易知道num 1 0,num...