1. 程式人生 > >全排列問題(三個衍生問題 )

全排列問題(三個衍生問題 )

鄙人不才,遇見的全排列問題和其衍生問題一共三種: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;
}