分治法(浅谈分治法)

分治算法的基本思想是将一个规模为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>
分治法里例子还有许多,比如比较经典的还有: 归并排序、快速排序


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值