问题描述: 设$R={r_1,r_2,…r_n}$是要进行排列的 n 个元素。其中元素$r_1,r_2,…r_n$可能相同。设设计一个算法,列出 R的所有不同排列。

算法设计: 给定 n及待排列的 n 个元素,计算出这 n个元素的所有不同排列。

数据输入: 由文件 input.txt 提供输入数据。文件的第 1 行是元素个数 n,$1 \leq n \leq 500$。接下来的 n 行是待排列的 n 个元素。

结果输出: 将计算出的 n个元素的所有不同排列输出到文件 output.txt。文件最后 1 行中是排列总数。

input.txt

4
aacc

output.txt

aacc
aacb
acac
acca
caac
caca
ccaa
6

#include <iostream>
#include <string>
using namespace std;

/*
以abcd为例,perm(abcd)
1、以a开头,则有bcd,bdc,cbd,cdb,dbc,dcb,记为(a)perm(bcd);递归定义,perm(bcd)也可以分解为(b)perm(cd), (c)perm(db), (d)perm(bc)...
2、同样,有(b)perm(acd)、(c)perm(adb)、(d)perm(bac);再继续递归定义...
3、知道最后perm(a), perm(b), perm(c), perm(d),其值为1

对于有重复的字符,只需加一步判断,判断之前出现的递归序列中有没有以该字母开头的情况
*/

int count=0;//记录总的排列数
bool available(string s,int k,int index){//判断是否有以c开头的排列,k为当前递归起始位置,index为当前字符的位置
    char c=s[index];
    for(int i=k;i<index;i++){
        if(s[i]==c) return false;
    }
    return true;
}
void perm(string s,int k,int m){//k为当前位置,m为字符串长度
    if(k==m-1){
        cout<<s<<endl;
        count++;
    }
    else{
        for(int i=k;i<m;i++){ if(!available(s,k,i))continue;//判断是否出现过 swap(s[k],s[i]);//交换当前位置与后面(包括当前位置)的字符,即代表不同字符开头的排列 perm(s,k+1,m); swap(s[k],s[i]);//回溯,恢复原状 } } } int main(){ string s; cin>>s;
    perm(s,0,s.length());
    cout<<"Total permutation number is: "<<count<<endl;
    return 0;
}