• 全排列打表


    全排列打表原理:

    递归实现:

    假设我们要对1,2,3,4四个数进行全排列,过程如下:
    (a)首先保持1不变,对2,3,4全排列;
    (b)保持2不变,对3,4全排列;
    (c)保持3不变,对4全排列,4的排列只有一种。得到1,2,3,4
    (d)然后3不能不变了,继续保持2不变,3,4互换得到1,2,4,3
    (e)以1,2打头的排列完成,接下来把3换到2的位置,继续(c)、(d)的操作
    ...

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    /*
    (1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀);
    (2)出口:如果递归到只有一个元素的全排列,则说明已经排完,则输出数组;
    (3)不断将每个元素放作第一个元素,然后将这个元素作为前缀,并将其余元素继续全排列,等到出口,出口出去后还需要还原数组; 
    */
    const int maxn = 1e5+10;
    int a[maxn],n;
    void dfs(int b[],int k){
        if(k==n){
            for(int i=1;i<=n;i++){
                printf("%d ",b[i]);
            }
            printf("
    ");
            return ;
        }
        for(int i=k;i<=n;i++){
            swap(a[i],a[k]);
            dfs(a,k+1);
            swap(a[i],a[k]);
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) a[i] = i;
        dfs(a,1);
        return 0;
    }

     关于STL中打印全排列表的使用:

    有关全排列函数:next_permutation(iterator start,iterator end),和prev_permutation(iterator start,iterator end);

    这两个函数作用是一样的,区别就在于前者求的是当前排列的下一个字典序排列,后一个求的是当前排列的上一个字典序排列   是否存在。

    进行自定义全排列 next_permutation(node,node+n,cmp

    next_permutation(num,num+n)函数是对数组num中的前n个元素进行全排列

    #include <stdio.h>
    #include <algorithm>
    using namespace std;
    int main(){
        int n;
        while(scanf("%d",&n)&&n){
            int a[1000];
            for(int i=0;i<n;i++){
                scanf("%d",&a[i]);
            }
            sort(a,a+n);
            do{
                for(int i=0;i<n;i++)
                    printf("%d ",a[i]);
                printf("
    ");
            }while(next_permutation(a,a+n));
        }
        return 0;
    }

     例题:

    2017第八届蓝桥杯-c++决赛A组 题目1

    题目:

    随意组合
    小明被绑架到X星球的巫师W那里。
    其时,W正在玩弄两组数据 (2 3 5 8) 和 (1 4 6 7)
    他命令小明从一组数据中分别取数与另一组中的数配对,共配成4对(组中的每个数必被用到)。
    小明的配法是:{(8,7),(5,6),(3,4),(2,1)}
    巫师凝视片刻,突然说这个配法太棒了!
    因为:
    每个配对中的数字组成两位数,求平方和,无论正倒,居然相等:
    87^2 + 56^2 + 34^2 + 21^2  =  12302
    78^2 + 65^2 + 43^2 + 12^2  =  12302
    小明想了想说:“这有什么奇怪呢,我们地球人都知道,随便配配也可以啊!”
    {(8,6),(5,4),(3,1),(2,7)}
    86^2 + 54^2 + 31^2 + 27^2 = 12002
    68^2 + 45^2 + 13^2 + 72^2 = 12002
    巫师顿时凌乱了。。。。。
    请你计算一下,包括上边给出的两种配法,巫师的两组数据一共有多少种配对方案具有该特征。
    配对方案计数时,不考虑配对的出现次序。
    就是说:
    {(8,7),(5,6),(3,4),(2,1)}
    与
    {(5,6),(8,7),(3,4),(2,1)}
    是同一种方案。
    注意:需要提交的是一个整数,不要填写任何多余内容(比如,解释说明文字等)
    View Code

    思路:

    由于给出的两个序列均只有4个值,所以我们可以全排列枚举匹配所有组成然后判值,如果相等则结果++

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    using namespace std;
    int a1[4]={2,3,5,8};
    int a2[4]={1,4,6,7};
    int ans=0;
    bool judge()
    {
        int b1[4],temp1=0;
        int b2[4],temp2=0;
        for(int i=0; i<4; i++)
        {
            b1[i]=a1[i]*10+a2[i];
            b2[i]=a1[i]+a2[i]*10;
            temp1+=b1[i]*b1[i];
            temp2+=b2[i]*b2[i];
        }
        if(temp1 == temp2) {
            return true;    
        }
    }
    //保证每一个元素不相同则输出全排列总个数为n! 
    void fun(int x)
    {
        if(x == 4)
        {
            if(judge())    ans++; 
            return;
        }
        //递归全排列 
        for(int i=x; i<4; i++)
        {
            swap(a1[i],a1[x]);
            fun(x+1);
            //回溯 
            swap(a1[i],a1[x]);
        }
    }
    int main()
    {
        fun(0);
        cout<<"ans: "<<ans<<endl; 
        return 0;     
    }
    View Code
  • 相关阅读:
    JAVA代码中加了Try...Catch的执行顺序
    Java的注解机制——Spring自动装配的实现原理
    UWP蓝牙的例子
    MIT License
    Windows 运行时组件
    VS 的编译选项 build下的 platform target -- Any CPU和x86有什么影响?
    swfdump——从内存中提取swf的工具
    生成某一文件夹内文件清单(批量处理)
    统一用户认证和单点登录解决方案
    关键路径计算、总时差、自由时差
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11604057.html
Copyright © 2020-2023  润新知