【2-5】有重復元素的排列問題


´問題描述:
設 R={ n
r ,r , ,r 1 2  }是要進行排列的 n 個元素。其中元素 n
r ,r , ,r 1 2  可能相同。試設計
一個算法,列出 R 的所有不同排列。
´編程任務:
給定 n 以及待排列的 n 個元素。計算出這 n 個元素的所有不同排列。
´數據輸入:
由文件 input.txt 提供輸入數據。文件的第 1 行是元素個數 n,1£n£500。接下來的 1 行
是待排列的 n 個元素。
´結果輸出:
程序運行結束時,將計算出的 n 個元素的所有不同排列輸出到文件 output.txt 中。文件
最后 1 行中的數是排列總數。
輸入文件示例 輸出文件示例
input.txt output.txt
4
aacc
aacc
acac
acca
caac
caca
ccaa
6

【題解】

枚舉當前位置要放的數字是什么然后和長度為len-1的排列接在一起成為長度為len的排列。 這種搜的方法的確更優秀點。 因為可以在搜的時候就把重復的數字直接排除掉。 設當前要確定的位置是L. 然后枚舉其要和后面某個位置交換。 假設是i. 則我們只要看看L..i-1這個區間里面的數字有沒有和a[i]相同的就可以了。 如果有相同的。那么之前肯定已經考慮過了(因為i是順序枚舉的).則直接跳過就行。 以前我寫的排列的方法要把所有的排列全都列出來。 事實上那樣 20 aaaa.aa(20個a) 這樣的情況就不能很快解決了 而這樣的枚舉方法可秒出解

【代碼】

#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 10;

int n,cnt;
char s[N+10];

template<class Type>
bool ok(Type a[],int l,int cur){
    for (int i = l;i < cur;i++){
        if (a[cur]==a[i]){
            return false;
        }
    }
    return true;
}

template<class Type>
void doit(Type a[],int l,int r){
    if (l==r){
        printf("%d:",++cnt);
        for (int i = 1;i <= r;i++){
            printf("%c ",a[i]);
        }
        puts("");
        return;
    }
    for (int k = l;k <= r;k++){
        if (ok(a,l,k)){
            swap(a[l],a[k]);
            doit(a,l+1,r);
            swap(a[l],a[k]);
        }
    }
}



int main(){
    scanf("%d",&n);
    scanf("%s",s+1);
    doit(s,1,n);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM