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

    全排列的递归实现虽然简单,但不容易理解。在绘制了一个树形结构图后,终于看清了里面的计算过程。但是虽然理清了过程,还是不明白为什么会这样设计。尤其是在递归调用的前后分别进行一次交换操作,感觉总是摸不着头绪。内心深处有个声音,往往让你绞尽脑汁不得其解的问题越是你的软肋。记得在高中学数学的时候,往往会因为一个数学难题而想破头想一个晚上,最终解出来之后总有种任通二脉打开的感觉,会感觉之前做过的类似的问题也会豁然开朗很多,虽然浪费了很长时间在这一个问题上,但收获却是无法估量的。

    工作之后,很难静下心来思考一个问题很长时间,尤其是算法问题。这就是考验一个人的关键时刻。静下心来,认真思考,浮躁只会让自己的困惑越积越多,直到困惑足以打破你的自信心,你就永远都无法在这个地方抬起头来!

    回头来思考这个问题,看到这个图之后清晰多了。我们看到,

    (1)以a开头后面跟着(b,c,d)的排列

    (2)以b开头后面跟着(a,c,d)的排列

    (3)以c开头后面跟着(a,b,d)的排列

    (4)以d开头后面跟着(a,b,c)的排列

    当前元素与它后面的元素(包含它自己)依次进行交换

    第一个swap是进行交换,而第二个swap是上一次swap的逆操作,为了防止上一次swap对之后产生影响。

    template <class T>
    inline void Swap(T& a, T& b)
    {
        // 交换a和b
        T temp = a; a = b; b = temp;
    }
     
    template<class T>
    void Perm(T list[], int k, int m)
    {
        //生成list [k:m ]的所有排列方式
        int i;
        if (k == m)
        {
             //输出一个排列方式
             for (i = 0; i <= m; i++)
                 cout << list [i];
             cout << endl;
        }
        else // list[k:m]有多个排列方式
        {
             // 递归地产生这些排列方式
             for (i=k; i <= m; i++)
             {
                 Swap (list[k], list[i]);
                 Perm (list, k+1, m);
                 Swap (list[k], list[i]);
             }
        }
    }

    非递归算法的实现过程

    //交换数组a中下标为i和j的两个元素的值
    void swap(int* a,int i,int j)
    {
        a[i]^=a[j];
        a[j]^=a[i];
        a[i]^=a[j];
    }
     
    //将数组a中的下标i到下标j之间的所有元素逆序倒置
    void reverse(int a[],int i,int j)
    {
        for(;i<j;++i,--j)
        {
             swap(a,i,j);
        }
    }
     
    void print(int a[],int length)
    {
        for(int i=0;i<length;++i)
             cout<<a[i]<<" ";
        cout<<endl;
    }
     
    //求取全排列,打印结果
    void combination(int a[],int length)
    {
        if(length<2) return;
     
        bool end=false;
        while(true)
        {
             print(a,length);
            
             int i,j;
             //找到不符合趋势的元素的下标i
             for(i=length-2;i>=0;--i)
             {
                 if(a[i]<a[i+1]) break;
                 else if(i==0) return;
             }
     
             for(j=length-1;j>i;--j)
             {
                 if(a[j]>a[i]) break;
             }
            
             swap(a,i,j);
             reverse(a,i+1,length-1);
        }
    }
  • 相关阅读:
    【洛谷P2927 [USACO08DEC]拼图游戏Jigsaw Puzzles】深搜
    【洛谷1219】 八皇后 (搜索)
    【Uva 12558】 Egyptian Fractions (HARD version) (迭代加深搜,IDA*)
    【转】DCX (数独-八皇后问题)
    【2016 11 14】 总结
    【HDU 3038】 How Many Answers Are Wrong (带权并查集)
    【POJ1182】 食物链 (带权并查集)
    【20161111双11模拟赛】总结
    【HDU 5381】 The sum of gcd (子区间的xx和,离线)
    【HDU 5233】Tree chain problem (树形DP+树剖+线段树|树状数组)最大权不相交树链集
  • 原文地址:https://www.cnblogs.com/sdlwlxf/p/4645917.html
Copyright © 2011-2022 走看看