分治法(浅谈分治法)

来源:互联网 发布:淘宝客 api 编辑:程序博客网 时间:2024/05/15 07:51

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。

步骤:

       1,划分问题:把问题的实力划分成子问题

       2,递归求解:递归解决子问题。

       3.  合并问题:合并子问题的解得到原问题的解。

      下面介绍一个例子。(帮助理解分治法)

       求最大连续和,给出一个长度为n的序列A1,A2,...An,求最大连续和。换句话说,要求找到1<=i<=j<=n,使得Ai+Ai+1+...+Aj最大

      分析:

              在本例中,“划分”就是把序列分成元素个数尽量相等的两半,“递归求解”就是分别求出完全位于左半或者右半的最佳序列;“合并”就是求出起点位于左半、终点位于右半的最大连续子序列的和,并和子问题的最优解比较。

            前两部分没有什么特别之处,关键在于“合并”步骤。既然起点位于左半,终点位于右半,则可以人为地把这样的序列分成两部分,然后独立求解,先寻找最佳起点,然后再寻找最佳终点。

       代码如下:

     

<span style="font-size:24px;">#include"stdio.h"#include"stdlib.h"#include"string.h"#include"algorithm"#include"math.h"using namespace std;//求最大连续和 //时间复杂度 O(nlogn) long long  maxsum(int a[],int x,int y)  //返回闭合区间【x,y】中最大的连续和 {    if(x==y)  return a[x];  //只有一个元素直接返回  //int m=(x+y)/2; int m=x+(y-x)/2;   //相比上一句,这样写更具有鲁棒性。     //分治的第一步,划分成【x,m】和【m+1,y】 两部分  long long  sum_max=max(maxsum(a,x,m),maxsum(a,m+1,y));   //分治法的第二步,递归求解(子问题的最优解)     long long  L_sum=0,R_sum=0,tem=0; for(int i=m;i>=x;i--)       L_sum=max(L_sum,tem+=a[i]); //分治法第三步(1),从分界点开始往左的最大连续和L  tem=0; for(int i=m+1;i<=y;i++)     R_sum=max(R_sum,tem+=a[i]); //分治法第三步(1),从分界点开始往右的最大连续和R  return max(sum_max,L_sum+R_sum);   //把子问题的解与 (L和R的和) 比较 } int main(){ int n,*a; scanf("%d",&n); a=(int *)malloc(sizeof(int)*n); for(int i=0;i<n;i++)    scanf("%d",&a[i]); printf("%lld\n",maxsum(a,0,n-1)); return 0;} </span>
分治法里例子还有许多,比如比较经典的还有: 归并排序、快速排序


1 0