7.2.1 生成1~n的排列

相比之下perm速度更快,但是print_perm似乎更加好理解一些

#include <stdio.h>
#include <iostream>

using namespace std;
int cnt;

    template <class Type>
void perm(Type list[], int k, int m)
{
    if(k > m)
    {
        for(int i = 1; i <= m ; i++)
            cout << list[i] << " ";
        cout << endl;
        cnt++;
    }

    else for(int i = k; i <= m; i++)
    {
        swap(list[k], list[i]);
        perm(list, k+1, m);
        swap(list[k], list[i]);
    }
}

void print_permutation(int n, int *A, int cur)
{
    int i, j;
    if(cur == n)
    {
        for(i = 0; i < n; i++) printf("%d ", A[i]);
        printf("\n");
        cnt++;
    }

    else for(i = 1; i <= n; i++)
    {
        int ok = 1;
        for(j = 0; j < cur; j++)
            if(A[j] == i) ok = 0;
        if(ok)
        {
            A[cur] = i;
            print_permutation(n, A, cur+1);
        }

    }
}

const int maxn = 10000;


int main()
{
    int m;
    int a[maxn];
    while(~scanf("%d", &m))
    {
        cnt = 0;
        for(int i = 0; i <= m; i++) a[i] = i;
        perm(a, 1, m);
        printf("%d\n", cnt);

        cout << endl << "print-perm: " << endl << endl;

        cnt = 0;
        for(int i = 0; i <= m; i++) a[i] = i;
        print_permutation(m, a, 0);
        printf("%d\n", cnt);
    }
    return 0;
}

7.2.2 生成可重集的排列

生成有重复元素的排列。此时算法设计书上的方法不太好用了。此外,需要注意的是,a要和p相同。

c#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>

using namespace std;
const int maxn = 10000;
int cnt;
int a[maxn];


void print_permutation(int n, int P[], int A[], int cur)
{
    int i, j;
    int c1, c2;
    if(cur == n)
    {
        for(i = 0; i < n; i++) printf("%d ", A[i]);
        printf("\n");
        cnt++;
    }

    else for(i = 0; i < n; i++) if(!i || P[i] != P[i-1])
    {
        c1 = 0, c2 = 0;
        for(j = 0; j < cur; j++) if(A[j] == P[i]) c1++;
        for(j = 0; j < n; j++) if(P[i] == P[j]) c2++;
        if(c1 < c2)
        {
            A[cur] = P[i];
            print_permutation(n, P, A, cur+1);
        }
    }
}



int main()
{
    freopen("input", "r", stdin);
    int m;
    int a[maxn], p[maxn];
    memset(a, 0, sizeof(a));
    memset(p, 0, sizeof(p));
    while(~scanf("%d", &m))
    {
        cnt = 0;
        for(int i = 0; i < m; i++)
            scanf("%d", &p[i]);

        sort(p, p+m);
        memcpy(a, p, sizeof(p));
        print_permutation(m, p, a, 0);
        printf("\n");
    }
    return 0;
}

利用STL生成组合

c#include <stdio.h>
#include <algorithm>

using namespace std;

int main()
{
    int n, p[10];
    scanf("%d", &n);
    for(int i = 0; i < n ;i++) scanf("%d", &p[i]);
    sort(p, p+n);

    do
    {
        for(int i = 0; i < n; i++) printf("%d ", p[i]);
        printf("\n");
    } while(next_permutation(p, p+n));
    return 0;
}

解答树

此外,在构造递归的过程中,可以构造解答树来简化问题。


svtter
209 声望37 粉丝

更喜欢原型开发