生成可重集的排列(方法)

通过暴力或者dfs的方法可以很容易地得到n个数的全排列,可生成可重集的呢,例如给出一个数组a[],要求输出这个数组的全排列,与普通的求全排列不同,数组中很可能存在重复的数,所以方法都需要改一改:

DFS

#include"iostream"
#include"cstring"
#include"cstdio"
using namespace std;
int n,book[21],a[21];
int ca=1;

void dfs(int step)
{
    if ((step == n))
    {
        for(int i=1; i<n; i++) cout<<a[i]<<' ';
        cout<<a[n]<<endl;
        return;
    }
    for(int i=1; i<=n; i++)
        if(book[i]<=2)          //这里表示重复的数最多可以有两个
        {
            a[step+1]=i;
            book[i]++;
            dfs(step+1);
            book[i]--;
        }
}
int main()
{
    int x=1;
    while(scanf("%d",&n)!=EOF)
    {
//a[1]=1;
        if(x>1) cout<<endl;
        x++;
        cout<<"Case "<<ca++<<':'<<endl;
        dfs(0);
    }
    return 0;
}
View Code

暴力:

#include"iostream"
#include"cstring"
#include"cstdio"
using namespace std;
int n,book[21],a[21];
int ca=1;


void print(int step)
{
    if ((step == n+1))
    {
        for(int i=1; i<n; i++) cout<<a[i]<<' ';
        cout<<a[n]<<endl;
    }

    for(int i=1; i<=n; i++)
    {
        int ok=1;
        for(int j=2; j<step; j++)     //这里j=2表示最多可以有2个重复的数
            if(a[j]==i) ok=0;
        if(ok)
        {
            a[step]=i;
            print(step+1);
        }
    }
}

int main()
{
    int x=1;
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        if(x>1) cout<<endl;
        x++;
        cout<<"Case "<<ca++<<':'<<endl;
        print(1);
    }
    return 0;
}
View Code

最后还有一个STL的函数,更简洁好用

#include"iostream"
#include"algorithm"
using namespace std;

int main()
{
    int n,p[10];
    while(cin>>n)
    {
        for(int i=0; i<n; i++) cin>>p[i];
        sort(p,p+n);
        do
        {
            for(int i=0; i<n; i++) cout<<p[i]<<' ';
            cout<<endl;
        }
        while(next_permutation(p,p+n));
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zsyacm666666/p/4680929.html