不可重集全排列字典序
(递归)
输入在数组p中,a是输出准备数组
#include<bits/stdc++.h>
using namespace std;
int n;
int p[10],a[10];
void print_permutation(int n,int *p,int *a,int cur)
{
if(cur==n)
{
for(int i=0;i<n;i++) printf("%d ",a[i]);
printf("\n");
}
else
{
for(int i=0;i<n;i++)
{
int ok=1;
for(int j=0;j<cur;j++)
if(a[j]==p[i]) ok=0;
if(ok)
{
a[cur]=p[i];
print_permutation(n,p,a,cur+1);
}
}
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",p+i);
sort(p,p+n);
/*
这里的sort看情况变化
必须先排序再调用递归。递归良序
*/
print_permutation(n,p,a,0);
}
可重集字典序全排列
用样例
3
1 1 1
测试上面代码会出现27个“111”
实际上同样的1调用1次即可
类似的 1 2 3 1 2 3,拍完序 1 1 2 2 3 3 ,同样的数字调用一次也恰好完成题意。可以加一个判断条件:如果i等于0或p[i]和上一个p[i-1]不同
随想:
if(!i||p[i]!=p[i-1]) .....
触发短路效应
下面代码的c1是元素已经在输出准备数组出现几次,c2是元素一共出现了几次。如果c1<c2,应该继续递归,也就是说同一个元素还应该被填充。
#include<bits/stdc++.h>
using namespace std;
int a[10],p[10],n;
int sum=0;
void print_permutation(int n,int *p,int *a,int cur)
{
if(cur==n) {
for(int i=0;i<n;i++) printf("%d ",a[i]);printf("\n");
sum++;
}
else
{
for(int i=0;i<n;i++)
{
int c1=0,c2=0;
for(int j=0;j<cur;j++) if(a[j]==p[i]) c1++;
for(int j=0;j<n;j++) if(p[i]==p[j]) c2++;
if(c1<c2&&(i==0||p[i]!=p[i-1]))
{
a[cur]=p[i];
print_permutation(n,p,a,cur+1);
}
}
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&p[i]);
sort(p,p+n);
print_permutation(n,p,a,0);
}
1.全排列非递归实现呢?—递归怎么写成非递归代码?实训深搜那题的非递归写法,学习学习。