全排列目前有两种方法,一种是递归式,另一种是运用STL,下面的代码是输出1--n的全排,运用的递归的方法,用stl输出会更简单,在这就不上代码了。
第一种递归全排(1-5的全排)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n=5;
int a[10];
bool vis[10];
//num 选取的第几个数
void dfs(int num) {
if (num == n+1) {
for (int i=1;i<=5;i++)
cout<<a[i]<<" ";
cout<<endl;
return ;
}
for (int i=1;i<=5;i++)
if (!vis[i]){
vis[i]=1;
a[num]=i;
dfs(num+1);
vis[i]=0;
}
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
dfs(1);
return 0;
}
第二种递归全排,类似上面的
#include<bits/stdc++.h>
using namespace std;
int a[200];
int n;
#define rep(i,a,b) for(int i=a;i<=b;i++)
void dfs(int num)
{
if(num==n)
{
rep(i,0,n-1)
cout<<setw(2)<<a[i];
cout<<endl;
}
rep(i,num,n-1)
{
swap(a[i],a[num]);
dfs(num+1);
swap(a[i],a[num]);
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n;
rep(i,0,n-1)
a[i]=i+1;
dfs(0);
return 0;
}
以上两种都是不能保证全排有重复的数列,下面是用递归处理有重复的全排
给出一个字符串S(可能有重复的字符),按照字典序从小到大,输出S包括的字符组成的所有排列。例如:S = "1312",
输出为:
1123
1132
1213
1231
1312
1321
2113
2131
2311
3112
3121
3211
Input
输入一个字符串S(S的长度 <= 9,且只包括0 - 9的阿拉伯数字)
Output
输出S所包含的字符组成的所有排列
Sample Input
1312
Sample Output
1123
1132
1213
1231
1312
1321
2113
2131
2311
3112
3121
3211
这是我用递归的方法进行全排的,但是没有控制好按字典序从小到大的输出顺序,结果WA,我想是因为,一开始已经将num数组按从小到大的顺序排好,但是在dfs函数用swap函数交换之后,原数组的顺序发生了改变,导致WA(这是上面的第二种代码的变形)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
int repsent;
char a[15];
int vis[15];
int b[20];
int M;
bool check(int num[],int a,int b)
{
for(int i=b;i>a;i--)
if(num[b]==num[i-1])
return false;
return true;
}
void dfs(int num[],int step) {
if (step == n) {
for (int i=0;i<n;i++)
cout<<num[i];
cout<<endl;
return;
}
for (int i=step;i<n;i++)
if (check(num,step,i))
{
swap(num[i],num[step]);
dfs(num,step+1);
swap(num[i],num[step]);
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int num[20];
gets(a);
n=strlen(a);
for(int i=0;i<n;i++)
num[i]=a[i]-'0';
sort(num,num+n);
dfs(num,0);
//cout<<M<<endl;
return 0;
}
借鉴的递归AC(上面第一种代码的变形)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
int repsent;
char a[15];
bool vis[15];
int b[20];
int M;
void dfs(int num[],int step) {
if (step == n) {
for (int i=0;i<n;i++)
cout<<b[i];
cout<<endl;
return;
}
for (int i=0;i<n;i++)
if (!vis[i])//判断下标为i的元素是否用过
{
vis[i]=1;
b[step]=num[i];
dfs(num,step+1);
vis[i]=0;
while(i<n-1&&num[i]==num[i+1])//这是对重复的元素全排的关键一步,对于样例1312来
i++;//说,经过sort排序之后,num={1,1,2,3},这样当第一个1全排完之后,又回到i=0
}//这一步,此时num[0]==num[1]的所以这一步直接跳过。还要补充的是,while里面必须是
}//num[i]==num[i+1]
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int num[20];
gets(a);
n=strlen(a);
for(int i=0;i<n;i++)
num[i]=a[i]-'0';
sort(num,num+n);//要做到从小到大输出,就要先将给的数据从小到大排列一下
dfs(num,0);
//cout<<M<<endl;
return 0;
}
附上简单的
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
char a[15];
int num[20];
bool vis[15];
//bool check(int num[],int a,int b)
//{
// for(int i=b;i>a;i--)
// if(num[b]==num[i-1])
// return false;
// return true;
//}
//void dfs(int num[],int step) {
// if (step == n) {
// for (int i=0;i<n;i++)
// cout<<b[i];
// cout<<endl;
//
// return;
// }
// for (int i=0;i<n;i++)
// if (!vis[i])
// {
// vis[i]=1;
// b[step]=num[i];
// dfs(num,step+1);
// vis[i]=0;
// while(i<n-1&&num[i]==num[i+1])
// i++;
// }
// }
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int num[20];
gets(a);
n=strlen(a);
for(int i=0;i<n;i++)
num[i]=a[i]-'0';
sort(num,num+n);
do
{
for(int i=0;i<n;i++)
cout<<num[i];
cout<<endl;
}while(next_permutation(num,num+n));
return 0;
}