zoukankan      html  css  js  c++  java
  • c++中的全排列

    next_permutation函数

        组合数学中经常用到排列,这里介绍一个计算序列全排列的函数:next_permutation(start,end),和prev_permutation(start,end)。这两个函数作用是一样的,区别就在于前者求的是当前排列的下一个排列,后一个求的是当前排列的上一个排列。至于这里的“前一个”和“后一个”,我们可以把它理解为序列的字典序的前后,严格来讲,就是对于当前序列pn,他的下一个序列pn+1满足:不存在另外的序列pm,使pn<pm<pn+1.

    对于next_permutation函数,其函数原型为:

         #include <algorithm>

         bool next_permutation(iterator start,iterator end)

    当当前序列不存在下一个排列时,函数返回false,否则返回true

    同时,相对应的,上一个排列即为prev_permutation(int *begin, int *end)

     看如下代码:

    #include <iostream>  
    #include <algorithm>  
    using namespace std;  
    int main()  
    {  
        int num[3]={1,2,3};  
        do  
        {  
            cout<<num[0]<<" "<<num[1]<<" "<<num[2]<<endl;  
        }while(next_permutation(num,num+3));  
        return 0;  
    }  

    运行结果如图:

    注意:当我们把while(next_permutation(num,num+3))中的3改为2时,输出就变为了下图所示:

    说明此时只针对1,2进行了全排列,有两个,后面的3没有变化,同时改变了数组前两个的值。

    由此可以看出,next_permutation(num,num+n)函数是对数组num中的前n个元素进行全排列,同时并改变num数组的值。

    另外,需要强调的是,next_permutation()在使用前需要对欲排列数组按升序排序,否则只能找出该序列之后的全排列数。

    比如,如果数组num初始化为3,1,2,那么输出就变为了:

    维基百科上全排列的实现:

    循环法:

    #include <iostream>
    using namespace std;
    bool arrsame(int* arr, int len, int num) {
        int i;
        for (i = 0; i < len; i++)
            if (arr[i] == num)
                break;
        return i != len;
    }
    bool next_perm(int* perm, const int k, const int n) {
        int i = k - 1;
        do
            perm[i]++;
        while (arrsame(perm, i, perm[i]) || (perm[i] >= n && i--));
        if (perm[0] >= n)
            return 0;
        for (int num = 0, seat = i + 1; seat < k; num++)
            if (!arrsame(perm, i + 1, num))
                perm[seat++] = num;
        return 1;
    }
    int main() {
        int n, k;
        cout << "perm(n,k):" << endl;
        cin >> n >> k;
        if (n < k || k <= 0)
            return 0;
        int* perm = new int[k];
        for (int i = 0; i < k; i++)
            perm[i] = i;
        do
            for (int i = 0; i < k; cout << ((++i < k) ? ',' : '
    '))
                cout << perm[i] + 1;
        while (next_perm(perm, k, n));
        delete[] perm;
        return 0;
    }

    递归法:

    #include <bits/stdc++.h>
    using namespace std;
    
    struct prem {
        int len;
        vector<int> used, position;
        function<void(vector<int>&)> action;
        prem(int l = 0, function<void(vector<int>&)> a = [](vector<int>& position) {}) : len(l), used(l, -1), position(l), action(a) {}
        void run(int now = -1) {
            if (now == len - 1) {
                action(position);
                return;
            }
            int next = now + 1;
            for (int i = 0; i < len; i++) {
                if (used[i] == -1) {
                    used[i] = next;
                    position[next] = i;
                    run(next);
                    used[i] = -1;
                }
            }
        }
    };
    int main() {
        ios::sync_with_stdio(false), cin.tie(0);
        int len = 4;
        prem p(len, [&](vector<int>& p) {
            for (int i = 0; i < len; i++) {
                cout << p[i] << " ";
            }
            cout << endl;
        });
        p.run();
        return 0;
    }

    next_permutation 可以自定义比较函数 例如:POJ 1256

    题目中要求的字典序是:A'<'a'<'B'<'b'<...<'Z'<'z',所以在用函数之前必须得按照题目要求的进行排序

    #include<iostream> //poj 1256 Anagram
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int cmp(char a,char b) 
    {
     if(tolower(a)!=tolower(b))//tolower 是将大写字母转化为小写字母.
     return tolower(a)<tolower(b);
     else
     return a<b;
    }
    int main()
    {
     char ch[20];
     int n;
    cin>>n;
     while(n--)
    {
    scanf("%s",ch);
    sort(ch,ch+strlen(ch),cmp);
     do
    {
    printf("%s
    ",ch);
    }while(next_permutation(ch,ch+strlen(ch),cmp));
    }
     return 0;
    }
    
     

    .

    不一样的烟火
  • 相关阅读:
    TCP/IP 协议简介
    制作html的旋转太极图
    Redis高可用
    RFID固定资产管理系统解决方案
    为什么要用三维数据可视化?
    Java单元测试技巧之PowerMock
    技术干货 | 如何在 Library 中使用/依赖 mPaaS?
    云原生的进一步具象化
    【阿里云EMR实战篇】以EMR测试集群版本为例,详解 Flink SQL Client 集成 Hive 使用步骤
    【实践案例】Databricks 数据洞察 Delta Lake 在基智科技(STEPONE)的应用实践
  • 原文地址:https://www.cnblogs.com/cstdio1/p/11311500.html
Copyright © 2011-2022 走看看