问题描述: 设$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;
}

最新评论