分治算法

分治的简明意思是:将大问题分成一个一个小问题,进行解决。

下面说说分治法解决问题的具体三个步骤(蕴含递归思想):

1.将原问题分解为一组子问题,每个子问题都与原问题类型相同,但是比原问题的规模小。

2.递归求解这些子问题。 

3.将子问题的求解结果恰当合并,得到原问题的解。

以上三条能够运用分治法完全取决于第二和第三条,若不符合可以考虑动态规划贪心法

根据分治法的分割原则,原问题应该分为多少个子问题才较适宜?各个子问题的规模应该怎样才为适当?这些问题很难予以肯定的回答。但人们从大量实践中发现,在用分治法设计算法时,最好使子问题的规模大致相同。换句话说,将一个问题分成大小相等的k个子问题的处理方法是行之有效的。许多问题可以取k=2。这种使子问题规模大致相等的做法是出自一种平衡(balancing)子问题的思想,它几乎总是比子问题规模不等的做法要好。

分治法的两种方式:

1自顶向下:就是上面说的解决步骤

2.自底向上:如果知道了最终直接可解的原子问题的全部情况,那么可采用由原子问题出发,向上递推的方法,由已有结论的小尺寸问题的解决,导致比它高一层次的同类问题的解决,最终使原问题彻底解决.这就是和递归向下方法对应的由底向上的分治方法的基本思路.

注:这个思想的关键是  分解

比较体现分治算法的具体例子:

快速排序,它的基本思想是:选择一个基准值,进行划分(比“基准值”小的元素居左边,比“基准值”大的元素居右边,基准值居中),然后对左右两半分别进行快速排序.这种划分不断进行,直到区域元素个数为1或0.这种尺寸为0或1的排序问题就是原子问题

另一个体现自底向上的思想的代码为:

Code:
  1. unsigned countbits(unsigned x)   
  2. {   
  3.     static unsigned mask[]={   
  4.         0x55555555, 0x33333333,   
  5.         0x0F0F0F0F, 0x00FF00FF,   
  6.         0x0000FFFF   
  7.     };   
  8.     for(unsigned i=0, shift=1; i<5; i++, shift<<=1)   
  9.     {   
  10.         x=(x&mask[i])+((x>>shift)&mask[i]);   
  11.     }   
  12.     return x;   
  13. }  

 以上代码请自行理解,以便你更好的理解分治算法。

..........................................................无敌分界线.......................................................

上面算法是求一个16进制数转换成2进制后一共含有几个1.也是最难想到的!

下面我们看看下面算法:

Code:
  1. #include <stdio.h>   
  2. unsigned countbits(unsigned x)   
  3. {   
  4.     unsigned n=0;   
  5.     while(x)   
  6.     {   
  7.         x =x & (x-1); //和自己的上一个数进行与运算,每次都会关掉一个1   
  8.         ++n; //记录   
  9.     }   
  10.     return n;   
  11. }   
  12.   
  13. int main(void)   
  14. {   
  15.     int m;   
  16.     while(scanf("%d",&m)!=EOF)   
  17.     {   
  18.         printf("二进制中含有的1一共有%d/n",countbits(m));   
  19.     }   
  20. }   

 

 


原文链接: http://blog.csdn.net/crazyjixiang/article/details/6465876

你可能感兴趣的:(分治算法)