全排列問題(三個衍生問題 )
阿新 • • 發佈:2018-11-10
鄙人不才,遇見的全排列問題和其衍生問題一共三種:1、無重複元素全排列問題。2、有重複元素全排列問題。3、n皇后問題
一、無重複元素全排列問題。給定一個數n,求從1~n的全排列。
看到網上教程很多都在說可以劃分為以下幾種情況: 以1開頭,2~n的全排列;以2開頭,1和3~n的全排列;...;n開頭,1~n-1的全排列。
這個方法很好理解,但不好想,也不好寫。真正理解要建立在對遞迴真瞭解的基礎之上。不太理解先彆著急,我們來總體分析一下(手動滑稽):一個函式,姑且叫它f(n),這個函式裡面有一個for迴圈,當迴圈裡的數滿足一定條件的時候,我們進行呼叫f(n),這樣,就是在迴圈中呼叫遞迴函式。當進行f(n)的時候,系統就會呼叫棧,自動地將當前的資料儲存在棧中,當遞迴返回時,就會執行f(n)的下一條語句。
好了,廢話了這麼多,也算是把鄙人對著這三個問題的理解寫出來了。其實只要這個問題理解了,剩下的有重複元素排列問題和n皇后問題很輕易就能理解程式碼。但是要注意,重複元素排列在拍之前要確定該數是否在之前出現過,n皇后問題我們用陣列下標表示列。
程式碼二:有重複元素排列問題:
#include <bits/stdc++.h> using namespace std; const int maxn = 1e4+110; char ch[maxn]; int cnt[maxn] = {0}; int tmp[maxn] = {0}; char num[maxn]; bool nt(int beg,int to) { for(int i=beg; i<to; i++) { if(ch[i] == ch[to]) return false; } return true; } void f(int n,int m) { if(n+1 == m) { for(int i=1; i<=n; i++) { cout<<num[i]; } cout<<endl; }else { int x; for(int i=1; i<=n; i++) { x = (int)ch[i]; // cout<<"x="<<x<<endl; if(tmp[x]<cnt[x] && nt(1,i)) //如果出現次數少於等於該元素的個數並且該元素在前面沒有出現過 { tmp[x]++; num[m] = ch[i]; f(n,m+1); tmp[x]--; } } } } int main() { cout<<"請輸入元素個數:"<<endl; int n,x; cin>>n; cout<<"請輸入元素"<<endl; for(int i=1; i<=n; i++) { cin>>ch[i]; x = (int)ch[i]; cnt[x]++; } //對有重複的序列進行排序 f(n,1); return 0; }