枚举排列

来源:互联网 发布:金融行业数据分析师 编辑:程序博客网 时间:2024/06/10 07:27
生成1~n的排列:
输入整数n,按字典序从小到大的顺序输出前n个数的所有排列。生成1~n的排列可以通过递归思想解决!

#include <algorithm>#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>#include <cmath>using namespace std;const int Max = 100000 + 10;int mem[Max];void solve(int n, int *a, int num){    if(num == n)///递归边界    {        for(int i = 0; i < n - 1; i++)            printf("%d ",a[i]);        printf("%d\n",a[n-1]);    }    else    {        for(int i = 1; i <= n; i++)///在a[num]中遍历一遍所有数        {            int ok = 0;            for(int j = 0; j < num; j++)            {                if(a[j] == i)///判断a[0]~a[num-1]是否出现过该数字,出现标记为1                    ok = 1;            }            if(!ok)            {                a[num] = i;                solve(n,a,num+1);            }        }    }    return;}int main(){    int n;    while (~scanf("%d",&n))    {       solve(n,mem,0);    }    return 0;}

生成可重集的排列:
输入数组q,并按字典序从小到大的顺序输出数组a各元素的所有全排列。生成可重集的排列同样是通过递归思想解想,需注意排列没有遗漏和重复!
#include <bits/stdc++.h>using namespace std;const int Max = 100000 + 10;int mem[Max], q[Max];void solve(int n, int *p, int *a, int num){    if(num == n)///递归边界    {        for(int i = 0; i < n - 1; i++)            printf("%d ",a[i]);        printf("%d\n",a[n-1]);    }    else    {        for(int i = 0; i < n; i++)///在a[num]中遍历一遍p数组中所有的数        {            int bj1 = 0, bj2 = 0;            if(!i || p[i] != p[i-1])///避免重复            {                for(int j = 0; j < num; j++)    if(a[j] == p[i])    bj1++;///统计a[0]~a[num-1]中p[i]的出现次数bj1;                for(int j = 0; j < n; j++)    if(p[i] == p[j])    bj2++;///统计p数组中p[i]的出现次数bj2;                if(bj1 < bj2)///避免遗漏                {                    a[num] = p[i];                    solve(n,p,a,num+1);                }            }        }    }    return;}int main(){    int n;    while (~scanf("%d",&n))    {        for(int i = 0; i < n; i++)            scanf("%d",&q[i]);        sort(q,q+n);        solve(n,q,mem,0);    }    return 0;}

除了上述的用递归来解决两个问题外,还可以用STL自带函数next_permutation来解决生成1 ~ n的排列、生成可重集的排列两个问题!next_permutation(mem,mem+n)表示对mem数组的mem[0] ~ mem[n]之间的数字按字典序进行排列!
#include <algorithm>#include <iostream>#include <string.h>#include <stdio.h>#include <math.h>using namespace std;const int Max = 100000 + 10;int n, mem[Max];void solve_int()///int 类型的 next_permutation 使用{    for(int i = 0; i < n; i++)        scanf("%d",&mem[i]);    sort(mem,mem+n);    do    {        for(int i = 0; i < n - 1; i++)            printf("%d ",mem[i]);        printf("%d\n",mem[n-1]);    }while(next_permutation(mem,mem+n));}void solve_char()///char 类型的 next_permutation 使用{    int len;    char ch[Max];    scanf("%s",ch);    len = strlen(ch);    sort(ch,ch+len);    do    {        printf("%s\n",ch);    }while(next_permutation(ch,ch+len));}void solve_string()///string 类型的 next_permutation 使用{    string str;    while(cin >> str && str != "*")    {        sort(str.begin(),str.end());        do        {            cout << str << endl;        }        while(next_permutation(str.begin(),str.end()));    }}bool cmp(char a, char b)///自定义排序顺序,'A' < 'a' < 'B' < 'b' ... < 'Z' < 'z'{    if(tolower(a) == tolower(b))        return a < b;    else        return tolower(a) < tolower(b);}void solve_mem()///自定义排序方法后 next_permutation 的使用{    int len;    char ch[Max];    scanf("%s",ch);    len = strlen(ch);    sort(ch,ch+len,cmp);    do    {        printf("%s\n",ch);    }while(next_permutation(ch,ch+len,cmp));}int main (){    scanf("%d", &n);    solve_int();    solve_char();    solve_string();    solve_mem();    return 0;}



0 0