精华内容
下载资源
问答
  • C - 顺序表应用7:最大子段和之分治递归
    2020-09-27 10:27:09

    C - 顺序表应用7:最大子段和之分治递归法

    Description

     给定n(1<=n<=50000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。

     

    注意:本题目要求用分治递归法求解,除了需要输出最大子段和的值之外,还需要输出求得该结果所需的递归调用总次数。

     

    递归调用总次数的获得,可以参考以下求菲波那切数列的代码段中全局变量count的用法:

    #include
    int count=0;
    int main()
    {
        int n,m;
        int fib(int n);
        scanf("%d",&n);
        m=fib(n);
        printf("%d %d\n",m,count);
        return 0;
    }
    int fib(int n)
    {
        int s;
        count++;
        if((n==1)||(n==0)) return 1;
        else s=fib(n-1)+fib(n-2);
        return s;
    }
     

    Input

    第一行输入整数n(1<=n<=50000),表示整数序列中的数据元素个数;

    第二行依次输入n个整数,对应顺序表中存放的每个数据元素值。

    Output

    一行输出两个整数,之间以空格间隔输出:

    第一个整数为所求的最大子段和;

    第二个整数为用分治递归法求解最大子段和时,递归函数被调用的总次数。

    Sample

    Input 

    6
    -2 11 -4 13 -5 -2

    Output 

    20 11

    分治法求解最大子段和,思想就是将数组分成左右两部分,分别求对应的子段和,最后还有一种可能,最大子段和处于左右两部分之间,所以我们要进行三次比较才能求出到底是哪一部分才是最大的子段和。其实不需要清楚每一步是怎么做的,我们只需要理解大致的想法,将代码交给计算机,具体细微的运算交给计算机去做。

    具体见代码注释。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    int a[100000]={0};//在宏观定义一个数组,其实没必要定义这么大的,比五万大一点即可 
    int flag=0;//计数变量,计算调用函数的次数 
    int sum=0;
    int max_function(int l,int r)//分治求最大字段和函数 
    {
    	flag++;//每次调用函数先加一 
    	if(l==r)//左等右,表示递归到最后一个 
    	{
    		if(a[l]>0)//如果数据大于零,就将sum初始化为此数据,如果小于0则不需要将sum等于
    		//因为如果数据小于0,定义子段和为0,最后一个数据也相当与一个长度为1的子段 
    			sum=a[l];
    		else
    			sum=0;
    	}
    	else//分治函数的主要部分 
    	{
    		int mid=(l+r)/2;//将数组一分为二进行分治 
    		int l_res=max_function(l,mid);//左半部分遍历 
    		int r_res=max_function(mid+1,r);//右半部分遍历 
    		int s=0;
    		for(int i=l;i<=r;i++)//遍历结束后,从最左边开始,到最右边,不断将sum与s进行比较 
    		{
    			if(s+a[i]>0)//s相当于从最左加到最右,分治法需要有三个结果进行比较,左半部分的sum
    			//右半部分的sum,以及一部分处于左边,一部分处于右边的子段构成的子段和s 
    				sum=max(sum,s=s+a[i]);
    			else
    				s=0;
    		}
    		sum=max(sum,l_res);//sum与s比较完之后与左半部分比较 
    		sum=max(sum,r_res);//sum与左半部分比较完后与右半部分比较 
    	}
    	return sum;//返回最大值 
    }
    int main()
    {
    	ios::sync_with_stdio(false);//提高输入输出效率。要加这一句话,不加的话会TLE
    	// c++中的cin和cout的效率比print和scanf 要低很多
    	//如果不想加这句话,就把输入输出换成print和scanf,如果用cin,cout的话就要加上 
    	int n,res;
    	cin>>n;
    	for(int i=0;i<n;i++)
    	{
    		cin>>a[i];
    	}
    	res=max_function(0,n-1);
    	cout<<res<<" "<<flag<<endl;
    //不要像下面那样输出,输出的flag一直为0,因为二者的输出是同时进行的,会导致函数中的flag变化了但是输出的flag依旧为初始值 
    //	cout<<max_function(0,n-1)<<" "<<flag<<endl; 
    	return 0;
    }

    本题时间要求比较严格,只有10ms,如果想用cin,cout进行数据的输入输出就必须写入 ios::sync_with_stdio(false);作用提高输入输出效率。对于cin,cout来说,5w的数据量在10ms处理完已经很吃力了。

    关于ios::sync_with_stdio(false);可以参考https://blog.csdn.net/weixin_44015865/article/details/84974373

    更多相关内容
  • 求数组元素的最大值,最小值(分治递归)(2015-06-19 08:56:23)标签:代码分类:算法//分治递归,求数组元素的最大值,最小值 public class Values { private int max; privateint min; public Values(int max,int min...

    求数组元素的最大值,最小值(分治递归)

    (2015-06-19 08:56:23)

    标签:

    代码

    分类:

    算法

    //分治递归,求数组元素的最大值,最小值 public class Values { private int max; private

    int min; public Values(int max,int min){ this.max=max;

    this.min=min; } public int getMax() { return max; } public void

    setMax(int max) { this.max = max; } public int getMin() { return

    min; } public void setMin(int min) { this.min = min; } } public

    class MinMax { public void min_max(int a[],int s,int e,Values

    values){ Values lValues=new Values(0,0); Values rValues=new

    Values(0,0); if(e==s+1||e==s){ if(a[s]>=a[e]){

    values.setMax(a[s]); values.setMin(a[e]); } else{

    values.setMax(a[e]); values.setMin(a[s]); } return; } int

    mid=(e+s)/2; min_max(a,mid+1,e,lValues); min_max(a,s,mid,rValues);

    values.setMax(lValues.getMax()>rValues.getMax()?lValues.getMax():rValues.getMax());

    values.setMin(lValues.getMin()=a[e]){ values.setMax(a[s]);

    values.setMin(a[e]); } else{ values.setMax(a[e]);

    values.setMin(a[s]); } return; } int mid=(e+s)/2;

    min_max(a,mid+1,e,lValues); min_max(a,s,mid,rValues);

    values.setMax(lValues.getMax()>rValues.getMax()?lValues.getMax():rValues.getMax());

    values.setMin(lValues.getMin()

    分享:

    a4c26d1e5885305701be709a3d33442f.png喜欢

    0

    a4c26d1e5885305701be709a3d33442f.png赠金笔

    加载中,请稍候......

    评论加载中,请稍候...

    发评论

    登录名: 密码: 找回密码 注册记住登录状态

    昵   称:

    评论并转载此博文

    a4c26d1e5885305701be709a3d33442f.png

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

    展开全文
  • 分治法一般是用递归实现的,且往往是均分,最常见的就是二分算法。 而在计算分治法的算法复杂性时,我们往往能得到这样一个关于复杂性公式T(n)的递推式: 其中, n为数据规模, k为分治后子规模运算的数量, m...

    分治法的算法复杂性计算

    • 分治法一般是用递归实现的,且往往是均分,最常见的就是二分算法。
    • 而在计算分治法的算法复杂性时,我们往往能得到这样一个关于复杂性公式T(n)的递推式:

    在这里插入图片描述

    • 其中,
    1. n为数据规模,
    2. k为分治后子规模运算的数量,这里要注意k并不就等于分治划分数m,可以理解为 原本n规模的运算 被划分为 k个n/m规模的运算
    3. m为规模的划分数,一般为二分,即m=2。
    4. f(n)为分治后需要进行的额外计算复杂度,一般为将多个划分连接起来的运算。

    • 对于此类计算,我们可以得到以下计算公式:
      在这里插入图片描述

    • 这样我们在分析分治递归算法时便能很快得到其算法复杂性。

    展开全文
  • 【算法设计与分析】 最大子段和(分治递归) 【问题描述】 使用分治递归算法解最大子段和问题,具体来说就是,将序列分为长度相等的左右两段,分别求出这两段的最大子段和,包含左右部分子段的最大子段和,求这三种...

    【算法设计与分析】 最大子段和(分治递归)

    【问题描述】
    使用分治递归算法解最大子段和问题,具体来说就是,将序列分为长度相等的左右两段,分别求出这两段的最大子段和,包含左右部分子段的最大子段和,求这三种情况得到的最大子段和的最大值。

    【输入形式】
    在屏幕上输入一个序列元素,包含负整数、0和正整数。

    【输出形式】
    序列的最大子段和,及得到最大子段和时的起始和终止编号。

    【样例输入】

    -2 11 -4 13 -5 -2
    

    【样例输出】

    20
    2
    4
    

    【样例说明】
    输入:6个数,元素间以空格分隔。
    输出:序列的最大子段和20,得到最大子段和时的起始编号为2,终止编号为4。

    【题解代码】

    C++代码:

    #include <iostream>
    #include <cstdio>
    #include <sstream>
    using namespace std;
    int a[100],t,n=0,ans=0,ansleft=0,ansright=0;
    int Maxsum(int left,int right,int &ansl,int &ansr)
    {
    	int l1=1,r1=1,l2=1,r2=1,l3=1,r3=1;
    	if(left==right)
    	{
    		if(a[left]>0)
    		{
    			ansl=ansr=left;
    			return a[left];
    		}
    		else
    			return 0;
    	}
    	else
    	{
    		int mid=left+(right-left)/2;
    		int sum1=Maxsum(left,mid,l1,r1);//情况1:最大子段与左半部分相同 
    		int sum2=Maxsum(mid+1,right,l2,r2);//情况2:最大子段与右半部分相同 
    		int sum3=0,s1=0,s2=0,temp1=0,temp2=0;//情况3:最大子段跨越左右两个部分 
    		for(int i=mid;i>=left;i--)
    		{
    			temp1+=a[i];
    			if(temp1>s1)
    			{
    				s1=temp1;
    				l3=i;
    			}
    		}
    		for(int i=mid+1;i<=right;i++)
    		{
    			temp2+=a[i];
    			if(temp2>s2)
    			{
    				s2=temp2;
    				r3=i;
    			}
    		}
    		sum3=s1+s2;
    		ansl=l3;
    		ansr=r3;
    		if(sum3<=sum1)
    		{
    			sum3=sum1;
    			ansl=l1;
    			ansr=r1;
    		}
    		if(sum3<=sum2)//细节:这里要用<= 
    		{
    			sum3=sum2;
    			ansl=l2;
    			ansr=r2;
    		}
    		return sum3;//最大子段优先选择:左>中>右 
    	}
    }
    int main()
    {
    	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    	stringstream scin;
    	string s;
    	getline(cin,s);
    	scin<<s;
    	while(scin>>t)
    		a[++n]=t;
    	ans=Maxsum(1,n,ansleft,ansright);
    	cout<<ans<<endl<<ansleft<<endl<<ansright<<endl;
    	return 0;
    }
    
    展开全文
  • 文章目录二、分治递归1、递归1.1、递归的思想1.2、选择排序1.3、生成排列1.4、如何求解递归方程2、分治2.1、分治的思想2.2、什么时候可以使用分治2.3、简单样例2.3.1、二分搜索2.3.2、快速排序2.3.3、归并排序2.4...
  • 注意,这篇文章是在基于我的上一篇凸包问题分治法写的,这些动态图也是基于我的那篇文章代码 先说说matplotlib怎么实现动态图: 在这里我用的是 matplotlib 里的animation.FuncAnimation FuncAnimation类的说明(在...
  • Input 第一行输入整数n(1<=n<=50000),表示整数序列中的数据元素个数;...第二个整数为用分治递归法求解最大子段和时,递归函数被调用的总次数。 Sample Input 6 -2 11 -4 13 -5 -2 Sample O...
  • 分治策略,将所有的选手分为两半,n个选手的比赛日程表就可以通过为n/2个选手设计的比赛日程表来决定。递归地用对选手进行分割,直到只剩下2个选手时,比赛日程表的制定就变得很简单。这时只要让这2个选手进行比赛...
  • 注意:本题目要求用分治递归法求解,除了需要输出最大子段和的值之外,还需要输出求得该结果所需的递归调用总次数。 递归调用总次数的获得,可以参考以下求菲波那切数列的代码段中全局变量count的用法: #include ...
  • 顺序表应用7:最大子段和之分治递归法Time Limit: 10MS Memory Limit: 400KBProblem Description 给定n(1当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1 注意...
  • 循环赛日程表是非常典型的分治递归的例子,也的一个稍微有点难的问题。但是,我相信大家一定没问题
  • 分治递归法中时间复杂度的推理

    千次阅读 2019-09-29 20:39:25
    时间复杂度的计算方法最直接的是count循环中...其中分治的递推式的概括原则来源于递归思想:当前值等于子递归的返回,所以当前的时间复杂度T(k)=T(k/2)+T(k/2)+O(k),其中k的值是计算的数据量。      
  • 采用递归分治法,类似于二分查找,找左边最大值和右边最大值,然后比较,返回比较大的那一个。递归的出口是当左下标>=右下标时,返回当前元素。 例:if(i>=j) return a[i]; 不多说了,思路比较简单,直接堆...
  • 深入理解分治法的算法思想,应用分治法解决实际的算法问题。 【实验性质】 验证性实验(学时数:2H) 【实验内容与要求】 1、设有n=2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:⑴每个选手...
  • 分治递归

    千次阅读 2019-06-11 21:14:34
    分治是解编程题常用的一种思想,而大多数数分治思想都是用递归来实现的。下面来分别介绍这两个概念,并给出它们的应用场景。 分治 分治(divide and conquer)的全称称为“分而治之”,分治即是将大问题划分为若干个...
  • 利用二路归并排序求逆序对,很巧妙的一种算法
  • 顺序表应用7:最大子段和之分治递归法 Time Limit: 10MS Memory Limit: 400KB Problem Description  给定n(1当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1。...
  • 分治算法(递归

    千次阅读 2020-05-13 12:43:54
    分治算法(递归)一、基本概念二、基本思想及策略三、分治法适用的情况四、分治法的基本步骤五、分治法的复杂性分析六、可使用分治法求解的一些经典问题七、依据分治法设计程序时的思维过程 一、基本概念 在计算机...
  • Strassen是采用分治算法的思想,将所给矩阵分成2阶矩阵 分治的方法循序渐进处理各个小矩阵的相乘,一个矩阵可以分成更多小的矩阵的。
  • n的全排列分治递归求解

    千次阅读 2019-10-03 22:54:35
    设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列。 设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。 集合X中元素的全排列记为perm(X)。 (ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列。...
  • 递归分治策略

    2018-08-05 13:14:51
    理解递归的概念。 掌握设计有效算法的分治策略。 通过下面的范例学习分治策略设计技巧。 大整数乘法; Strassen矩阵乘法; 棋盘覆盖; 合并排序 循环赛日程表 递归算法:直接或者间接调用自身的算法称为递归算法。 ...
  • 实现并验证合并排序算法; Ex2:实现并验证快速排序算法 Ex3:用递归分治的方法设计并实现寻找第k小元素算法
  • 下面给出应用最小堆方法的两个程序,最后再贴上利用分治递归法的代码,虽然时间复杂度不及堆方法,但思路相对简单好理解。 (1)最小堆方法1 用一个大小为K的最小堆(用优先队列+自定义降序实现)(优先队列就是大...
  • 1知识点:分治递归法求最大子段和顺序表应用7:最大子段和之分治递归法——SDUT题目链接 Time Limit: 10MS Memory Limit: 400KBProblem Description 给定n(1)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a...
  • }//此算法编程方式参考分治的版本 测试数据(两组,执行两次): 5 input 5 4 3 2 1 1 2 3 4 5 output 7 input 3 45 12 34 5 44 8 3 6 8 12 34 44 45 output

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 72,324
精华内容 28,929
关键字:

分治递归

友情链接: 理论力学.rar