算法:分治总结

    xiaoxiao2026-02-28  5

      分治法的基本思想:把一个规模为n的问题分解为k个规模较小的自问题,这些子问题互相独立且与原问题相同。

      一般的算法设计模式:

     Divide-and-Conquer(P)

    {

      if(|P|<=n0)

      Adhoc(P);

      divide P into smaller subinstances

      P1,P2,...,Pk;

      for(int i = 1;i <= k;++i)

      yi = Divide-and-Conquer(Pi);

      return Merge(y1,y2,...,yk);

    }

    |P|表示问题的规格

    n0表示当P规模不超过n0那么问题就已经容易解决不需要去分解

    Adhoc(P)是该分治算法的基本子算法,当规模不超过n0就可以直接用它得出结果

    Merge()的作用是该分治算法中的合并子算法,将所有子问题的解合并成P的解

    例子,就是一个合并排序

    template<class Type> void Merge(Type *sd,Type *si,int left,int m,int right) { int i = left,j = m+1; int k = left; while(i<=m && j<= right) { sd[k++] = si[i] < si[j]? si[i++]:si[j++]; } while(i<=m) { sd[k++] = si[i++]; } while(j<=right) { sd[k++] = si[j++]; } } template<class Type> void MergePass(Type *ar,Type *br,int n,int s) {// s = 2; // 0 1 2 3 //4 5 6 7 //8 9 cout<<"s = "<<s<<endl; for(int i = 0;i+2*s-1 <= n-1; i+=2*s) { Merge(ar,br,i,i+s-1,i+2*s-1); cout<<i<<" "<<i+s-1<<" "<<i+2*s-1<<endl; } if(n-1 > i+s-1) { Merge(ar,br,i,i+s-1,n-1); cout<<i<<" "<<i+s-1<<" "<<n-1<<endl; } else//两个作用,一个是预防后面没有值了,还有一个是确保br给了ar,这个看后面你就懂了 { for(int j = i;j<n;++j) { ar[j] = br[j]; } } Print_Array(ar,n); }

    template<class Type> void MergeSort(Type *ar,int n) { Type *br = new Type[n]; int s = 1; while(s < n) { MergePass(br,ar,n,s);//分治,分成小段小段,顺便的MergePass完成了分治中的合并子算法,和子算法的计算 s+=s; MergePass(ar,br,n,s);//同上,顺便把所有数据给ar s+=s; } delete []br; }

    在用分治法设计算法时,最好使子问题的规模大致相同,即将一个问题分成大小相等的k个子问题的处理方法是行之有效的。

    分治算法棋盘覆盖的思路:

    采用的是L型骨牌覆盖棋盘

    (1)先看2*2,有一个点和其他的不同,另外三个被同一个L给覆盖了

    (2)递推2^2*2^2,如果左上的2*2有,那么[1][2],[2][2],[2][1]构成了一个L,然后再分看,四个部分各一个L就补全了

    要是8*8那么[3][4],[4][3],[4][4],找出规律,n*n,[n/2-1][n/2],[n/2][n/2-1],[n][n]构成第一个,然后n=n/2,一直到n=1为止

    void CheseBoard(Array ar,int tr,int tc,int dr,int dc,int size)

    dr,dc表示特殊点所在的位置,行列,tr,tc,棋盘左上角放个行号,棋盘左上角方格列号

    转载请注明原文地址: https://ju.6miu.com/read-1307450.html
    最新回复(0)