分治法求最大子段和问题

合集下载

最大子段和-分治法

最大子段和-分治法
printf("最大字段和是:%d\n",t);
}
//求序列a[left]~a[right]的最大子段和
int max_sum(int a[],int left,int right)
{
int i,j,sum=0;
int s1=0,s2=0,lefts=0,rights=0;
void main()
{
int i,n,a[100],t;
printf("请输入数列的个数(<99):\n");
scanf("%d",&n);
printf("请输入数列元素:\n");
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
t=max_sum(a,1,n);
lefts=lefts+a[i];
if(lefts>s1)
s1=lefts;
}
//再求解s2
for(j=center+1;j<=right;j++)
{
rights=rights+a[j];
if(rights>=max_sum(a,left,center); //对应情况1,递归求解
rightsum=max_sum(a,center+1,right); //对应情况2,递归求解
//求解s1
for(i=center;i>=left;i--)
{
2:最大子段和在第二个序列,3:最大子段和在第一个序列与第二个序列之间。

算法(复习题)1

算法(复习题)1

平均情况:设待查找的元素在数组中的概率为P,不在数组中的概率为1-P,若出现在数组中每个位置的概率是均等的为p/nT(n)=P1D1+P2D2+...+PiDi+(1-P)Dn+1=p/2+n(1-p/2)1.叙述分治算法和动态规划算法的基本思想,并比较两种算法的异同。

答:分治法将待求解的问题划分成K个较小规模的子问题,对这K个子问题分别求解,再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出原问题的解. 动态规划将待求解的问题分解成若干的子问题,自底向上地通过求解子问题的解得到原问题的解。

动态规划将每个子问题只求解一次并将其解保存在一个表格中,当需要再次求解此子问题时,只是简单的通过查表过的该子问题的解,避免了大量的重复计算.异同:分治法求解的问题分解后的子问题都是独立的,而使用动态规划求解的问题分解后得到的子问题往往不是相互独立的。

分治法是自顶向下用递归的方法解决问题,而动态规划则是自底向上非递归解决问题。

1.简述分治算法求解过程的三个阶段。

答:(1)划分:既然是分治,当然需要把规模为n的原问题划分为k个规模较小的子问题,并尽量使这k个子问题的规模大致相同。

(2)求解子问题:各子问题的解法与原问题的解法通常是相同的,可以用递归的方法求解各个子问题,有时递归处理也可以用循环来实现。

(3)合并:把各个子问题的解合并起来,合并的代价因情况不同有很大差异,分治算法的有效性很大程度上依赖于合并的实现。

2.叙述分治法的基本思想,并分析分治法与减治法二者的区别。

答:分治法将待求解的问题划分成K个较小规模的子问题,对这K个子问题分别求解,再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出原问题的解.区别:分治法是把一个大问题划分成若干个子问题,分别求解各个子问题,然后把子问题的解进行合并并得到原问题的解。

减治法同样是把一个大问题划分成若干个子问题,但是这些子问题不需要分别求解,只需求解其中的一个子问题,因而也无需对子问题的解进行合并。

最大子段和问题的简单算法

最大子段和问题的简单算法

最大子段和问题的简单算法一、引言最大子段和问题(Maximum Subarray Sum Problem)是计算机科学中一个经典的问题,旨在寻找数组中的连续子数组,使得该子数组中所有元素的总和最大。

这个问题的解决方法有多种,其中包括暴力解法、分治法、动态规划等。

本篇文章将介绍一种简单且高效的解决方法——Kadane算法。

二、算法描述Kadane算法是一种基于动态规划的贪心算法,其基本思想是对于给定的数组,不断选择以当前元素结尾的最大子段和,然后将这个最大子段和更新为全局最大子段和。

算法的主要步骤如下:1. 初始化两个变量,一个是局部最大和max_ending_here,初值为数组的第一个元素;另一个是全局最大和max_global,初值为数组的第一个元素。

2. 遍历数组中的每个元素,对于当前元素,计算以当前元素结尾的最大子段和max_ending_here,然后更新全局最大和max_global。

3. 在遍历过程中,对于每个元素,都会计算出一个以该元素结尾的最大子段和,因此遍历结束后,全局最大和就是最大的子段和。

三、算法复杂度分析Kadane算法的时间复杂度为O(n),其中n是数组的长度。

因为我们需要遍历数组中的每个元素一次。

在空间复杂度方面,Kadane算法只需要常数级别的额外空间来存储两个变量,因此其空间复杂度为O(1)。

四、算法实现下面是一个用Python实现的Kadane算法:def max_subarray_sum(arr):max_ending_here = max_global = arr[0]for i in range(1, len(arr)):max_ending_here =max(arr[i], max_ending_here + arr[i])max_global =max(max_global, max_ending_here)return max_global五、结论Kadane算法是一种简单且高效的解决最大子段和问题的方法,其时间复杂度为O(n),空间复杂度为O(1)。

区间dp知识点总结

区间dp知识点总结

区间dp知识点总结区间动态规划以区间为基本单位,将区间问题分解为子区间问题,并通过子问题的优化解来求解原问题的最优解。

在区间动态规划中,我们通常会先对区间进行预处理,然后进行状态转移和最优解的计算,最终得出整个区间的最优解。

本文将介绍区间动态规划的基本概念、相关术语、常用技巧和应用场景,并以具体的例题进行解析,希望能够帮助读者更好地理解并掌握区间动态规划的相关知识。

一、基本概念1. 区间在区间动态规划中,区间通常是指一段连续的序列,可以是数组、字符串或其他数据结构。

如有一个长度为n的数组,通常我们可以将数组的某个子区间[i, j]表示为数组的一段连续元素,其中i和j分别为区间的左右边界。

2. 状态在区间动态规划中,状态通常用来表示问题的解空间,它是问题的一个关键要素。

状态的选择不同,可能会导致不同的算法解法。

3. 状态转移方程区间动态规划的核心是状态转移方程,它描述了问题的状态如何转移,以及如何通过子问题的最优解来求解原问题的最优解。

状态转移方程通常包括两个方面:状态之间的转移关系和状态的初始值。

4. 最优解区间动态规划通常是要求解区间范围内的最优解问题。

最优解可能是指区间的最大值、最小值、最长子序列等。

二、相关术语1. 最长上升子序列(Longest Increasing Subsequence,简称LIS)最长上升子序列是指一个序列中各个元素都严格递增的子序列,且该子序列的长度最大。

在区间动态规划中,求解最长上升子序列的长度是一个常见的问题。

2. 最大子段和(Maximum Subarray Sum)最大子段和是指一个序列中连续元素的和中最大的值。

在区间动态规划中,求解最大子段和也是一个常见的问题。

3. 背包问题背包问题是一类经典的组合优化问题,它包括 0-1 背包问题、多重背包问题、分组背包问题等。

在区间动态规划中,背包问题的求解也是一个重要的应用场景。

4. 字符串处理字符串处理是区间动态规划中一个重要的应用场景,常见的问题包括编辑距离、最长公共子序列、最长回文子串等。

算法分析考试题

算法分析考试题

1. )(n T 给定数组a[0:n-1],试设计一个算法,在最坏情况下用n+[logn]-2次比较找出a[0:n-1] 中的元素的最大值和次大值. (算法分析与设计习题 2.16 ) (分治法)a 、 算法思想用分治法求最大值和次大值首先将问题划分,即将划分成长度相等的两个序列,递归求出左边的最大值次大值,再求出右边的的最大值次大值,比较左右两边,最后得出问题的解。

b 、复杂度分析:把问题划分为左右两种的情况,需要分别递归求解,时间复杂度可如下计算:有递推公式为:T(n)=1 n=1T(n)= 2T(n/2)+1 n>1所以,分治算法的时间复杂度是n+[logn]-2,当n 为奇数时,logn 取上线,当n 为偶数时,logn 取下线。

//不知道为什么会-2!C 、代码实现:#include <stdio.h>int a[100]; void maxcmax(int i,int j,int &max,int &cmax){int lmax,lcmax,rmax,rcmax;int mid;if (i==j){ max=a[i];cmax=a[i];}else if (i==j-1)if (a[i]<a[j]){max=a[j];cmax=a[i];}else{max=a[i];cmax=a[j];}else{mid=(i+j)/2;maxcmax(i,mid,lmax,lcmax);maxcmax(mid+1,j,rmax,rcmax);if(lmax>rmax)if(lcmax>rmax){max=lmax;。

cmax=lcmax;}else{max=lmax;cmax=rmax;}elseif(rcmax>lmax){if(rmax==rcmax){max=rmax;cmax=lmax;}else{max=rmax;cmax=rcmax;}}。

三种方法求解最大子区间和:DP、前缀和、分治

三种方法求解最大子区间和:DP、前缀和、分治

三种⽅法求解最⼤⼦区间和:DP、前缀和、分治题⽬洛⾕:LeetCode:给出⼀个长度为n的序列a,选出其中连续且⾮空的⼀段使得这段和最⼤。

挺经典的⼀道题⽬,下⾯分别介绍O(n) 的 DP 做法、前缀和做法,以及O(n log n) 的分治做法。

DP 做法⽤d i表⽰结尾为位置i的最⼤区间和,则有d i=max(d i−1,0)+a i问题的答案即为max{d i∣i∈[1,n]}。

编写代码时不需要开d数组,⽤变量 last_d 记录d i−1,变量 ans 记录max{d i},并在扫描时动态更新即可。

时间复杂度O(n),空间复杂度O(1)。

核⼼代码如下:maxn = int(2e5 + 5)arr = [0 for _ in range(maxn)] # 从下标 1 开始存# 输⼊过程略……ans = Nonelast_d = 0for i in range(1, n + 1):temp_ans = max(last_d, 0) + arr[i]if ans is None or temp_ans > ans:ans = temp_anslast_d = temp_ansprint(ans)前缀和做法将数列前n项的和记为sum n:sum n=n ∑i=1a i可以⽤前缀和快速求区间和:y∑i=x a i=sum y−sum x−1⽤d i表⽰结尾为位置i的最⼤区间和,则有d i=sum i−min{sum j∣j<i}问题的答案即为max{d i∣i∈[1,n]}。

编写代码时只需要开前缀和数组,⽆需开d数组,⽤变量 cur_min_pre_sum 记录min{sum j},变量 ans 记录max{d i},并动态维护即可。

时间复杂度O(n),空间复杂度O(n)。

核⼼代码如下:maxn = int(2e5 + 5)arr = [0 for _ in range(maxn)] # 原数组,从下标 1 开始存pre_sum = [0 for _ in range(maxn)] # 前缀和数组# 输⼊过程略……# 预处理前缀和for i in range(1, n + 1):pre_sum[i] = pre_sum[i - 1] + arr[i]cur_min_pre_sum = 0ans = Nonefor i in range(1, n + 1):temp_ans = pre_sum[i] - cur_min_pre_sumif ans is None or temp_ans > ans:ans = temp_anscur_min_pre_sum = min(cur_min_pre_sum, pre_sum[i])print(ans)分治做法若有⼀区间 [start,stop),区间中点为mid,其最⼤⼦段和对应的⼦区间为 [i,j),则 [i,j) 只有以下三种情况:[i,j) 完全在左⼦区间 [start,mid) 内;[i,j) 完全在右⼦区间 [mid,stop) 内;[i,j) 横跨中点mid。

分治法求解最大子段和

分治法求解最大子段和

返回目录
核心代码
int Divide_Conquer(int a[], int left, int right, int *begin, int *end) { int center; int left_left, left_right, leftSum; int right_left, right_right, rightSum; int cross_left, cross_right, crossSum; if (left == right) { *begin = left; *end = right; return a[left]; } center = (left+right)/2; //左边的最大子段和 leftSum = Divide_Conquer(a, left, center, &left_left, &left_right); //右边最大子段和 rightSum = Divide_Conquer(a, center+1, right, &right_left, &right_right); //中间最大子段和 crossSum = find_max_crossing_subarray(a, left, center, right, &cross_left, &cross_right);
返回目录
核心代码
int find_max_crossing_subarray(int a[], int left, int center, int right, int* cross_left, int* cross_right)//寻找跨越中间的最大子段和 { int i; int leftSum; int sum; int rightSum; sum = a[center]; leftSum = a[center]; *cross_left = center; for (i = center-1; i >= left; i--) { sum += a[i]; if (sum > leftSum) { leftSum = sum; *cross_left = i; } }

软件工程专升本测试题含答案

软件工程专升本测试题含答案

软件工程测试题含答案一、单选题(共30题,每题1分,共30分)1、若一棵二叉树具有8个度为2的结点,5个度为1的结点,则度为0的结点个数是?A、不确定B、6C、11D、9正确答案:D2、$1$TLGHx5co$vq6xM0WG1hYfIV1AZEWgD是什么系统的密码加密值?()A、UNIXB、AIXC、WindowsD、Linux正确答案:D3、在JDBC端抛出“SQL check failed!”的异常信息,原因分析正确的是?A、违规SQL语句被隔离装置拒绝执行B、真实数据库和虚拟式数据库配置错误C、业务系统应用服务器地址检查失败D、webservice自动重连测试SQL语句告警正确答案:A4、array[0]的含义是A、取当前array中第一个元素B、错误操作C、取当前array中最后一个元素D、赋值为0正确答案:A5、()加密算法属于公钥密码算法。

A、IDEAB、RSAC、AESD、DES正确答案:B6、神经网络的基本思想是什么A、将计算变得复杂B、得到更多的参数C、得到更合适的特征D、将计算效率提高正确答案:C7、下列哪种算法更适合做时间序列建模A、贝叶斯算法B、LSTMC、决策树D、CNN正确答案:B8、设某文件经内排序后得到100个初始归并段(初始顺串),若使用多路归并排序算法,且要求三趟归并完成排序,问归并路数最少为A、6B、8C、7D、5正确答案:D9、采用分治法计算最大子段和时间复杂度为A、O(n2)B、O(logn)C、O(n)D、O(nlogn)正确答案:D10、下列个工具包属于集成算法A、pandasB、tensorflowC、xgboostD、numpy正确答案:C11、特征工程的目的是什么A、找到最合适的算法B、加快计算速度C、得到最好的输入数据D、减低模型复杂度正确答案:C12、可变分区存储管理在收回一个空闲区后,空闲区数目可能会()A、减少一个B、保持不变C、增加一个D、上述A、B、C都有可能正确答案:D13、下列哪一项是神经网络的组成部分A、词袋模型B、激活函数C、信息增益D、核函数正确答案:B14、下列哪一项是随机森林的优势A、建模时可动态调整样本权重B、不可并行计算C、基于梯度下降求解速度更快D、输出结果更稳定正确答案:D15、当你感觉到你的Win2003运行速度明显减慢,当打开任务管理器后发现CPU使用率达到了100%,你认为你最有可能受到了()攻击。

【分析】算法分析与设计作业参考答案

【分析】算法分析与设计作业参考答案

【关键字】分析《算法分析与设计》作业参考答案作业一一、名词解释:1.递归算法:直接或间接地调用自身的算法称为递归算法。

2.程序:程序是算法用某种程序设计语言的具体实现。

2、简答题:1.算法需要满足哪些性质?简述之。

算法是若干指令的有穷序列,满足性质:1)输入:有零个或多个外部量作为算法的输入。

2)输出:算法产生至少一个量作为输出。

3)确定性:组成算法的每条指令清晰、无歧义。

4)有限性:算法中每条指令的执行次数有限,执行每条指令的时间也有限。

2.简要分析分治法能解决的问题具有的特征。

分析分治法能解决的问题主要具有如下特征:1)该问题的规模缩小到一定的程度就可以容易地解决;2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;3)利用该问题分解出的子问题的解可以合并为该问题的解;4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

3.简要分析在递归算法中消除递归调用,将递归算法转化为非递归算法的方法。

将递归算法转化为非递归算法的方法主要有:1)采用一个用户定义的栈来模拟系统的递归调用工作栈。

该方法通用性强,但本质上还是递归,只不过人工做了本来由编译器做的事情,优化效果不明显。

2)用递推来实现递归函数。

3)通过Cooper变换、反演变换能将一些递归转化为尾递归,从而迭代求出结果。

后两种方法在时空复杂度上均有较大改善,但其适用范围有限。

三、算法编写及算法应用分析题:1.冒泡排序算法的基本运算如下:for i ←1 to n-1 dofor j ←1 to n-i doif a[j]<a[j+1] then交换a[j]、a[j+1];分析该算法的时间复杂性。

解答:排序算法的基本运算步为元素比较,冒泡排序算法的时间复杂性就是求比较次数与n的关系。

1)设比较一次花时间1;2)内循环次数为:n-i次,(i=1,…n),花时间为:3)外循环次数为:n-1,花时间为:2.设计一个分治算法计算一棵二叉树的高度。

最大字段和问题

最大字段和问题

最⼤字段和问题最⼤⼦段和 -- 分治,dp1.问题描述输⼊⼀个整型数组,数组中的⼀个或连续多个整数组成⼀个⼦数组。

求所有⼦数组的和的最⼤值。

⽰例1:输⼊: nums = [-2,1,-3,4,-1,2,1,-5,4]输出: 6解释: 连续⼦数组 [4,-1,2,1] 的和最⼤,为 6。

2.分析问题2.1 ⽅案1此题很显然可以⽤多层for循环解决, 时间复杂度为O(n^2) .2.2 ⽅案2, 图像压缩问题的变形采⽤dp的思路, 我们把这个数组分成不同的段, **dp[i] 表⽰以nums[i]结尾的那个段的最⼤字段和, 所以就存在nums[i]这个元素是加⼊前⼀段中, 还是⾃成⼀段这就是需要思考的问题, 如果dp[i-1] < 0, 如果nums[i]加⼊前⼀段中, 最⼤字段和为dp[i-1] + nums[i], 这个值必然⼩于nums[i], 因为dp[i-1]是负数, 负数加上⼀个数,必然⽐这个数⼩, 就像是⼀个数减了某个数, 肯定变⼩. 其他情况下只⽤求dp[i-1] + nums[i]和 nums[i] 的最⼤值即可 **通过上⾯的分析, 很容易写出状态转移⽅程// dp初始化dp[0] = nums[0]if(dp[i-1] < 0) dp[i] = nums[i]; // ⾃成⼀段if(dp[i-1] >= 0) dp[i] = Max(dp[i-1] + nums[i], nums[i])简化转移⽅程, dp[i-1]<0时, nums[i] + dp[i-1] 必然是⼩于nums[i]的, 其实也是在求Max(dp[i-1] + nums[i], nums[i]),所以这个题只⽤⼀个⽅程就搞定. 简化了if else的判断, 对程序性能提升也是有帮助的dp[0] = nums[0]dp[i] = Max(dp[i-1] + nums[i], nums[i])这个题很有个很坑的地⽅就是, dp中最后⼀个元素并不是最终要求的结果, 这个我们平时做的题有很⼤的出⼊, dp[i]的含义是以nums[i]结尾的那个段的最⼤字段和, 那么dp中最后⼀个元素表⽰的是以nums中最后⼀个元素结尾的那个段的最⼤字段和, 最⼤的字段和不⼀定以nums中最后⼀个元素结尾,所以要最终要求的⽬标是dp数组中的最⼤值public int maxSubArray(int[] nums) {if(nums == null || nums.length <= 0) throw new IllegalArgumentException();int[] dp = new int[nums.length];dp[0] = nums[0];for(int i = 1; i < nums.length; ++i){dp[i] = Math.max(nums[i], nums[i] + dp[i-1]);}// return dp[nums.length-1]; 神坑int maxValue = Integer.MIN_VALUE;for(int j = 0; j < dp.length; ++j){if(dp[j] > maxValue)maxValue = dp[j];}return maxValue;3. ⽅案3采⽤分治的思路, 我们把数组从中间分开, 最⼤⼦序列的位置就存在以下三种情况最⼤⼦序列在左半边, 采⽤递归解决最⼤⼦序列在右半边, 采⽤递归解决最⼤⼦序列横跨左右半边, 左边的最⼤值加上右边的最⼤值时间复杂度分析T(n) = 2 F(n/2) + n时间复杂度O(nlgn)public int maxSubArray(int[] nums) {if(nums == null || nums.length <= 0) throw new IllegalArgumentException(); return helper(nums, 0, nums.length-1);}private int helper(int [] nums, int start, int end){if(nums == null || nums.length <= 0) throw new IllegalArgumentException(); if(start == end)return nums[start];int middle = start + (end - start) / 2;int leftSums = helper(nums,start, middle);int rightSums = helper(nums,middle+1, end);// 横跨左右两边int leftRightSums;// 左边的最⼤值int lsums = Integer.MIN_VALUE, temp = 0;for(int i = middle; i >= start; i--){temp += nums[i];if(temp > lsums)lsums = temp;}// 右边的最⼤值int rsums = Integer.MIN_VALUE;temp = 0;for(int j = middle+1; j <= end; j++){temp += nums[j];if(temp > rsums) rsums = temp;}leftRightSums = rsums + lsums;return Math.max(Math.max(leftSums, rightSums), leftRightSums);}。

算法实验3-最大子段和问题实验报告

算法实验3-最大子段和问题实验报告

昆明理工大学信息工程与自动化学院学生实验报告( 2011 — 2012 学年 第 1 学期 )课程名称:算法设计与分析 开课实验室:信自楼机房444 2012 年12月 14日一、上机目的及内容1.上机内容给定有n 个整数(可能有负整数)组成的序列(a 1,a 2,…,a n ),求改序列形如∑=jk ka1的子段和的最大值,当所有整数均为负整数时,其最大子段和为0。

2.上机目的(1)复习数据结构课程的相关知识,实现课程间的平滑过渡; (2)掌握并应用算法的数学分析和后验分析方法;(3)理解这样一个观点:不同的算法能够解决相同的问题,这些算法的解题思路不同,复杂程度不同,解题效率也不同。

二、实验原理及基本技术路线图(方框原理图或程序流程图)(1)分别用蛮力法、分治法和动态规划法设计最大子段和问题的算法; 蛮力法设计原理:利用3个for 的嵌套(实现从第1个数开始计算子段长度为1,2,3…n 的子段和,同理计算出第2个数开始的长度为1,2,3…n-1的子段和,依次类推到第n 个数开始计算的长为1的子段和)和一个if (用来比较大小),将其所有子段的和计算出来并将最大子段和赋值给summax1。

用了3个for 嵌套所以时间复杂性为○(n 3);分治法设计原理:1)、划分:按照平衡子问题的原则,将序列(1a ,2a ,…,na )划分成长度相同的两个字序列(1a ,…,⎣⎦2/n a )和(⎣⎦12/+n a ,…,na )。

2)、求解子问题:对于划分阶段的情况分别的两段可用递归求解,如果最大子段和在两端之间需要分别计算s1=⎣⎦⎣⎦)2/1(max2/n i an ik k≤≤∑=,s2=⎣⎦⎣⎦)2/(max12/n j n ajn k k≤≤∑+=,则s1+s2为最大子段和。

若然只在左边或右边,那就好办了,前者视s1为summax2,后者视s2 o summax2。

3)、合并:比较在划分阶段的3种情况下的最大子段和,取三者之中的较大者为原问题的解。

解决问题常用方法

解决问题常用方法

解决问题的常用方法
分治法(归并排序,最大子和段问题)基本思想:将一个难以直接解决的大问题分解成一些规模较小的相同问题,以便各个击破,分而治之。

如规模为n的问题可分解成k个子问题,1<k≤n,这些子问题互相独立且与原问题相同。

分治法产生的子问题往往是原问题的较小规模。

步骤:(1)分解:将原问题分解成一系列子问题。

(2)求解:递归地求解各个子问题。

若子问题足够小,则直接求解。

(3)合并:将子问题的解合并成原问题的解。

动态规划法(0-1背包问题,最长公共子序列问题;寻找最优解)基本思想:将带求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。

经分解得到的子问题往往不是独立的,在过程当中,可以用一个表来记录所有已解决的子问题的答案,不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。

步骤:(1)找出最优解的性质,并刻画其结构特征;
(2)递归地定义最优解的值;
(3)以自底向上的方式计算出最优值;
(4)根据计算最优值时得到的信息,构造一个最优解。

贪心算法(活动选择,背包问题):当前每一步都是最优的,是当前最好的选择,但不一定是最优解。

回溯法(0-1背包,n皇后问题):。

最大字段和问题

最大字段和问题

课堂回顾
• 要考察以a[f]为尾元素的每一个子段,就是要枚举以a[f]为尾 元素的每一个子段的首元素的下标位置。以a[f]为尾元素的 子段有很多,包括a[1],a[2],a[3],a[4],a[5],…, a[f]、 a[2],a[3],a[4],a[5],…,a[f]、a[3],a[4],a[5],…, a[f]、a[4],a[5],…,a[f],……、a[f]可以按照从f到1的顺 序去枚举首元素的下标,这样可以充分利用上一次计算的结 果。因为按照从f到1的顺序去枚举首元素的下标,以a[f]为 尾元素的第一个子段就是a[f];以a[f]为尾元素的第二个子段 就是a[f-1],a[f],显然这个子段只比上一个子段多了一个当 前子段的首元素而以;以a[f]为尾元素的第三个子段就是a[f2],a[f-1],a[f],显然这个子段也只比上一个子段多了一个 当前子段的首元素。这样,当前子段的和就等于上一个子段 的和再加上当前子段的首元素。如果当前子段的和等于sum ,就找到了和最大的子段,只需记录当前子段的首元素即可 ,反之就继续考察以a[f]为尾元素的下一个子段,直至找到 和最大的子段的首元素为止。找到了首尾元素的下标,就构 造出了问题的最优解。
课堂回顾
1 .最优子结构性质
• 假设子段{a[s],a[s+1],…,a[j-1],a[j]}是以a[j]为尾元素 的最大子段,也就是说b[j]=sum{a[s]……a[j]}。那么必有 子段{a[s], a[s+1],…,a[j-1]}一定是以a[j-1]为尾元素的 最大子段,也就是说必有b[j-1]= sum{a[s]……a[j-1]}。问 题的最优解中包含了子问题的最优解,最优子结构性质成 立。
课堂回顾
• 先求以数组元素a[1]为尾元素的最大子段和,再求以数组元 素a[2]为尾元素的最大子段和,依此类推,一直求到以数组 元素a[n]为尾元素的最大子段和,则整个数组的最大子段和 就是这n个最大子段和中的最大者 • 若用数组元素b[j]来表示以数组元素a[j]为尾元素的最大子段 和,则整个数组的最大子段和就是b[j],于是求整个数组的 最大子段和就转化为求各个b[j]

动态规划模拟题及答案

动态规划模拟题及答案

动态规划测试题一:填空题(每空2分,共20分)1.动态规划算法的步骤是(找出最优解的性质,并刻画其结构特征)、(递归地定义最优值)(以自底向上的方式计算最优值)、(根据计算最优值时得到的信息构造最优解)。

2.为方便起见、将矩阵连乘积A i A i+1……A j简记为(A[i:j] )。

3.动态规划算法的两个基本要素是(最优子结构性质)和(重叠子问题性质)。

4.矩阵连乘问题的算法可由(递归)设计实现。

5.对于矩阵连乘问题、设计算A[i:j]、1≤i≤j≤n,所需要的最少数乘次数为m[i][j],则原则问题的最优值为(m[1][n] )。

6. 动态规划算法的基本思想是将待求解问题分解成若干(子问题),先求解(子问题),然后从这些(子问题)的解得到原问题的解。

二:综合题(第一题5分其余各题15分,共50分)1.补充下面的最大子段和动态规划算法。

int MaxSum(int n,int *a){int sum=0,b=0;for(int i=1;i<=n;i++){if(b>0){b+=a[i];besti=1;}else b=a[i];if(b>sum){sum=b;bestj=i;}}return sum;}2. 0—1背包问题:有5种物品,背包的容量为c=10,物品i的重量为wi,其价值为vi:(w1,v1)=(2,6) (w2,v2)=(2,3) (w3,v3)=(6,5) (w4、v4)=(5,4)(w5,v5)=(4,6), 求最优解及最优值。

解∵p[5+1]={(0,0)}又∵(w5,w5)=(4,6)∴q[5+1]=p[5+1]○+(4,6)={(4,6)}则p[5]=m5j-其中的受控点={(0,0),(4,6)}又∵(w4,v4)=(5,4)∴q[5]○+(w4,v4)={(0,0),(4,6)}○+(5,4)={(5,4),(9,10)}∴w4j=p[5]∨q[5]={(0,0),(4,6),(5,4),(9,10)}又∵(w3,v3)=(6,5)∴q[4]=p[4]○+(w3,v3)={(6,5),(10,11)}∴m3j=p[4]∨q[4]={(0,0),(4,6),(6,5),(9,10),(10,11)} 则p[3]=m3j-其中的受控点={(0,0),(4,6),(9,10),(10,11)}又∵(w2,v2)=(2,3)∴q[3]=p[3]○+(w2,v2)={(2,3),(6,9)}∴m2j={(0,0),(2,3),(4,6), (6,9),(9,10),(10,11) } p[2]=m2j-其中的受控点={(0,0),(2,3),(4,6),(6,9),(9,10),(10,11)}又∵(w1,v1)=(2,6)∴q[2]=p[2]○+(w2,v2)={(2,6),(4,9),(6,12),(8,15)}∴m1j={(0,0),92,3},(2,6),(4,6),(4,9),(6,9),(6,12),(8,15),(9,10),(10,11)}∴p[1]={(0,0),(2,6),(4,9),(6,12),(8,15)}∴此0—1问题的最优值15.最优解为p[1]={(0,0),(2,6),(4,9)(6,12),(8,15)}3.设n=4,(a1,a2,a3,a4)=(3,4,8.10),(b1,b2,b3,b4)=(6,2,9,15),求作业中的一种最优调度方案并计算其最优值。

算法 分治法

算法 分治法

13
27
38 50
55
65 49
i
j
i
j
13 27 38 49 50 55 65
2021/8/1
分治法
20
算法4.6——快速排序
void QuickSort(int r[ ], int first, int end)
{ if (first<end) { pivot=Partition(r, first, end); //问题分解,pivot是轴值在序列中的位置 QuickSort(r, first, pivot-1); //递归地对左侧子序列进行快速排序 QuickSort(r, pivot+1, end); //递归地对右侧子序列进行快速排序
66的旋转方阵
2021/8/1
分治法
8/56
4.2 排序问题中的分治法
4.2.1 归并排序 4.2.2 快速排序
2021/8/1
分治法
9
4.3.1 归并排序
二路归并排序的分治策略是: (1)划分:将待排序序列r1, r2, …, rn划分为两个 长度相等的子序列r1, …, rn/2和rn/2+1, …, rn; (2)求解子问题:分别对这两个子序列进行排 序,得到两个有序子序列; (3)合并:将这两个有序子序列合并成一个有 序序列。
//对应情况①,递归求解 rightsum=MaxSum(a, center+1, right);
//对应情况②,递归求解
2021/8/1
分治法
30
s1=0; lefts=0;
//以下对应情况③,先求解s1
for (i=center; i>=left; i--)
{

最大子段(全)

最大子段(全)
最大子段和——分治与动态规划 问题:
给定n个整数(可能为负数)组成的序列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[1n]分成a[1n/2]和a[n/2+1n],则a[1n]的最大字段和有三种情况:
**(1)a[1n]的最大子段和与a[1n/2]的最大子段和相同
**(2)a[1n]的最大子段和与a[n/2n]的最大子段和相同
**(3)a[1n]的最大子段和为ai++aj,1<=i<=n/2,n/2+1<=j<=n
int center=(l+r)/2;
int lsum=MaxSum_DIV(v,l,center);
int rsum=MaxSum_DIV(v,center+1,r);
int s1=0;
int lefts=0;
**T(n)=2T(n/2)+O(n)
**T(n)=O(nlogn)
*/
int MaxSum_DIV(int *v,int l,int r)
{
int k,sum=0;
if(l==r)
return v[l]>=0?v[l]:0;
else
{
for (k=center+1;k<=r;k++)
{
rights+=v[k];

分治法求最大子段和问题

分治法求最大子段和问题

分治法求最大子段和问题共有四种方法:算法一;算法三;算法三、Divide and Conquer算法四源代码、On-line Algorithm算法一源代码:/*Given (possibly negative) integers Al, A2, •: AN, find the maximum value.找最大子段和*7# include<stdio.h>#include <time.h>#include <windows.h>int MaxSubsequenceSum(int A[],int N);main(){int LN/A,MaxSumjudge;LARGEJNTEGER begin z end,frequency; 〃代表64位有符号整数,记录程序运行时间QueryPerformanceFrequency(&frequency);//oJ'以获得当前的处理器的频率printff输入整数的个数:”);scanf(”%cT&N);A=(int *)malloc(N*sizeof(int)); //用数组给数据动态分配空间printf("自行输入数据请按1,随机产生数据请按2\n"); scanf(,,%d,,,&judge);if(judge==l){ 〃自行输入数据printff■输入%d 个整数:“,N);for(i=0;i<N;i++)scanf(”%d”,&A[i]);}else{printf(“随机产生的%d个整数为:\n“,N); 〃用随机种子随机产生N个0-999的整数srand(time(0));for (i=0;i<N;i++){if(rand()%2==0) 〃利用随机数奇偶性的等概率使得正负数约各占一半A[i]=ra nd()%1000;elseA[i]=(-l)*rand()%1000; printf("%d\t",A[i]);}}QueryPerformanceCounter(&begin); 〃记录算法1 开始时间MaxSum=MaxSubsequenceSum(A,N);QueryPerformanceCounter(&end); 〃记录算法1 终止时间printf(H\n 最大子段和为:%d\n H,MaxSum);printff 算法 1 运行时间为:%fsecon ds\n,,/(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart);// 终止时间■开始时间 =算法1运行时间systemCpause");} int MaxSubsequenceSum(int A[],int N){int ThisSum,MaxSum=O,i,j,k; 〃对最大值初始化for(i=0;i<N;i++) 〃从A[i]开始for(戸;j<N;j++){ 〃以A[j]结束ThisSum=0;for(k=i;k<=j;k++)ThisSum+=A[k]; 〃从A[i倒A[j]求和if(ThisSum>MaxSum)MaxSum=ThisSum; 〃更新最人值}return MaxSum;}算法2源代码:/*Given (possibly negative) integers Al, A2, •: AN, find the maximum value.找最大子段和*7# include<stdio.h>#include <time.h>#include <windows.h>int MaxSubsequenceSum(int A[],int N);main(){int i z N,*A,MaxSumjudge;LARGEJNTEGER begin z end,frequency; 〃代表64位有符号整数,记录程序运行时间QueryPerformanceFrequency(&frequency);//oJ'以获得当前的处理器的频率printff*输入整数的个数:");scanf(”%cT&N);A=(int *)malloc(N*sizeof(int)); //用数组给数据动态分配空间printf("自行输入数据请按1,随机产生数据请按2\n"); scanf(,,%d,,,&judge);if(judge==l){ 〃自行输入数据printff■输入%d 个整数:“,N);for(i=0;i<N;i++)scanf( ”%d”,&A[i]);}else{printf「随机产生的%:1个整数为:\『:N); 〃用随机种子随机产生N个0-999的整数srand(time(0));for (i=0;i<N;i++){if(rand()%2==0) 〃利用随机数奇偶性的等概率使得正负数约各占一半A[i]=ra nd()%1000;elseA[i]=(-l)*rand()%1000;printf(”%d\t“,A[i]);}}QueryPerformanceCounter(&begin); 〃记录算法2 开始时间MaxSum=MaxSubsequenceSum(A,N);QueryPerformanceCounter(&end); 〃记录算法2 终止时间printf("\n 最大子段和为:%d\n"z MaxSum);printff1算法2 运行时间为:%f seconds\n M,(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart); 〃终止时间■开始时间二算法2运行时间systemCpause");}int MaxSubsequenceSum(int A[],int N){int ThisSum^axSum^JJ; 〃对最人值初始化for(i=0;i<N;i++){ 〃从A[i]开始ThisSum=0;for(戸;j<N;j++){ 〃以A[j]结束ThisSum+=A[j]; 〃从A[i倒A[j]求和if(ThisSum>MaxSum)MaxSum=ThisSum; 〃更新最人值}}return MaxSum;}算法三源代码:分治法/*Given (possibly negative) integers Al, A2Z•: AN, find the maximum value.找最大子段和*7 # include<stdio.h>#include <time.h>#include <windows.h>int Divide_Conquer(int a[]Jnt leftjnt right);main()int i^/A,MaxSumjudge;LARGEJNTEGER begin,end,frequency; 〃代表64位有符号整数,记录程序运行时河QueryPerformanceFrequency(&frequency);//oJ'以获得当前的处理器的频率printff*输入整数的个数:");scanfC%cT&N);A=(int *)malloc(N*sizeof(int)); //用数组给数据动态分配空间printf("自行输入数据请按1,随机产生数据请按2\n");scanf(,,%d,,/&judge);if(judge==l){ 〃自行输入数据printf(“输A%d 个整数:“,N);for(i=0;i<N;i++)scanf(”%d”,&A[i]);}else{printf(”随机产生的%:1个整数为:\n“,N);〃用随机种子随机产生N个0-999的整数srand(time(0));for (i=0;i<N;i++){if(rand()%2==0) 〃利用随机数奇偶性的等概率使得正负数约各占一半A[i]=ra nd()%1000;elseA[i]=(-l)*rand()%1000;printf(”%d\t",A[i]);}}QueryPerformanceCounter(&begin); 〃记录算法3 开始时河MaxSum=Divide_Co nquer(AQN);QueryPerformanceCounter(&end); 〃记录算法3 终止时间printf("\n 最大子段和为:%d\n"z MaxSum);printff 算法3 运行时间为:%f secon ds\n,,/(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart); 〃终11:时间-开始时间二算法3运行时间systemCpause");}int Divide_Conquer(int a[]Jnt left,int right)//分治算法{int sum=0Jeftsum=0/rightsum=0,ce nterj;if(left==right){if(a[left]>0)sum=a[left];elsesum=0;else{center=(left+right)/2; 〃将数据一分为2leftsum=Divide_Conquer(a z left,center); 〃递归求左边区间的数据的最大子段rightsum=Divide_Conquer(a,center+l,right); //递归求右边区间的数据的最大子段int sl=O,lefts=O;for(i=center;i>=left;i-){ //求左边区间的数据的最大子段lefts+=a[i]; if(lefts>=sl) sl=lefts;}int s2=0/rights=0;for(i=center+l;i<=right;i++){//求右边区间的数据的最大子段rights+=a[i];if(rights>=s2) s2=rights;}sum=sl+s2;if(sum<leftsum) 〃最丿€ 值更新sum=leftsum;讦(sum<rightsum)sum=rightsum;}return sum;}算法四源代码:On-line Algorithm/*Given (possibly negative) integers Al, A2, •: AN, find the maximum value.找最大子段和*7# include<stdio.h>#include <time.h>#include <windows.h>int MaxSubsequenceSum(int A[],int N);main(){int MaxSumjudge;LARGEJNTEGER begin z end,frequency; 〃代表64位有符号整数,记录程序运行时间QueryPerformanceFrequency(&frequency);//oJ'以获得当前的处理器的频率printff输入整数的个数:");scanf(”%cT&N);A=(int *)malloc(N*sizeof(int)); //用数组给数据动态分配空间printf("自行输入数据请按1,随机产生数据请按2\n"); scanf(,,%d,,,&judge);if(judge==l){ //自行输入数据printf「输入%4个整数:鳥N);for(i=0;i<N;i++)scanf( ”%d”,&A[i]);}else{printf(”随机产生的%:1个整数为:\n“,N);〃用随机种子随机产生N个0-999的整数srand(time(0));for (i=0;i<N;i++){if(rand()%2==0) 〃利用随机数奇偶性的等概率使得正负数约各占一半A[i]=ra nd()%1000;elseA[i]=(-l)*rand()%1000;printf(“%d\t“,A[i]);}}QueryPerformanceCounter(&begin); 〃记录算法4 开始时间MaxSum=MaxSubsequenceSum(A,N);QueryPerformanceCounter(&end); 〃记录算法4 终止时间printf("\n 最大子段和为:%d\n",MaxSum);printff 算法4 运行时间为:%f seconds\n,,/(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart);// 终止时间■开始时间二算法1运行时间systemCpause");}int MaxSubsequenceSum(int A[],int N){int ThisSum^axSumj;ThisSum=0;MaxSum=0; 〃对最人值初始化for(j=0;j<N;j++){ 〃从A[j]开始ThisSum += A[j]; 〃从A[i倒A[j]求和if(ThisSum>MaxSum)MaxSum=ThisSum; 〃更新最人值else if(ThisSum<0)ThisSum=0; 〃若和为负,则为0,舍去return MaxSum;。

分治法的基本思想

分治法的基本思想

七、分治法1、分治法的基本思想任何一个可以用计算机求解的问题所需的计算时间都与其规模N有关。

问题的规模越小,越容易直接求解,解题所需的计算时间也越少。

例如,对于n个元素的排序问题,当n=1时,不需任何计算;n=2时,只要作一次比较即可排好序;n=3时只要作3次比较即可,…。

而当n较大时,问题就不那么容易处理了。

要想直接解决一个规模较大的问题,有时是相当困难的。

分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。

如果原问题可分割成k个子问题2、分治法的适用条件分治法所能解决的问题一般具有以下几个特征:(1)该问题的规模缩小到一定的程度就可以容易地解决;(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;(3)利用该问题分解出的子问题的解可以合并为该问题的解;(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

上述的第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;第二条特征是应用分治法的前提,它也是大多数问题可以满足的,此特征反映了递归思想的应用;第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑贪心法或动态规划法。

第四条特征涉及到分治法的效率,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。

3、分治法的基本步骤分治法在每一层递归上都有三个步骤:(1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;(2)解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;(3)合并:将各个子问题的解合并为原问题的解。

它的一般的算法设计模式如下:Divide_and_Conquer(P)if |P|≤n0then return(ADHOC(P))将P分解为较小的子问题P1、P2、…、Pkfor i←1 to kdoyi ←Divide-and-Conquer(Pi)△递归解决PiT ←MERGE(y1,y2,…,yk)△合并子问题Return(T)其中|P| 表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。

线段差的最大值的原理

线段差的最大值的原理

线段差的最大值的原理
线段差的最大值是指在一系列线段中最大差值的问题。

它可以与问题中涉及的线段数
量有关。

一般来说,如果一系列线段的数量多,则最大差值也会更大。

当考虑该问题时,
可以通过计算最大线段差值来解决。

解决问题最常用的方法是分治法。

分治法要求将一个问题分解成更小的子问题,再有
效解决这些子问题来获得最优的解决方法。

对于线段差的最大值的问题,分治法的思路是,将线段分为两部分,先求解两部分线段的最大值,然后将这两部分最大值的最大值作为该
问题的最大值。

整体的步骤如下:
1.将线段分为两部分,分别求解其中最大值;
2.取两部分的最大值的最大值作为该问题的最大值;
3.从求解过程中取线段差值作为最大值;
4.重复上述步骤,递归求解,最终确定最大线段差值。

因此,通过分治法解决线段差的最大值,可以更快捷地求解该问题。

在实际应用中,
分治法可以实现快速和有效的结果,提高工作效率。

CSP-S2021初赛解析

CSP-S2021初赛解析

CSP-S2021初赛解析⼀、单项选择解析1.选A,ls列出⽬录,cd是定位⽬录,cp是复制问卷,all只有作为命令的参数使⽤2.选B,00101010+00010110010000003.选A,递归函数的参数和局部变量存储在系统栈,如果层数过多,栈就会溢出。

解析4.选C,排序稳不稳定看相等值得元素排序后得相对位置有没有变化,因此元素之间得⽐较只要是相邻的,排序就是稳定的,⽽堆排序元素的⽐较跨度很⼤。

5.选Ca1与a2⽐,消耗⽐较次数1次,不妨令a1>=a2剩下的2n-2个数,两两⽐较,消耗次数n-1次,产⽣n-1个更⼤的数,n-1个更⼩的数a1与剩下的n-1个更⼤的数依次⽐较,消耗次数n-1次a2与剩下的n-1个更⼩的数依次⽐较,消耗次数n-1次总的消耗次数S=1+(n−1)+(n−1)+(n−1)=3n−26.选C初始哈希表如下:012345678910h[0]=0,h[1]=1,h[2]=4,h[3]=9,h[4]=5,h[5]=3,哈希表如下:012345678910h[6]==3——>h[6]=4−−>h[6]=5−−>h[6]==6,哈希表如下:012345678910h[7]=5−−>h[7]=6−−>h[7]=77.选C不考虑题⽬限制的不连通状态,e=36,则⾄少需要的点数n满⾜完全图,e=n(n−1)2−−>n=9,因为题⽬要求不连通状态,所以再加⼀个孤⽴的点。

解析8.选B令⼆叉树的⾼度位h,题意求最少的⾼度,要满⾜趋于满⼆叉树的状态;满⼆叉树的情况下其结点个数n=2h−1, 选项A,210−1=1023,排除,选项B,211−1=2047,只需最后⼀层减掉26个节点就可以满⾜.9.选D如果树上某个结点A存在左⼦树B和右⼦树C,那么在前序遍历的顺序是A-B-C,中序遍历则是B-A-C,显然,把B去掉两个序列相同。

10.选A类似冒泡排序求逆序对,存在7个逆序对解析11.选Asolve(23,23) <-- 5∗solve(22,23)mod n <-- 52∗solve(21,23)mod n <-- ... 522∗solve(1,23)mod n根据费马⼩定理:a p mod p=a mod p (p为质数)a p−1mod p=1mod p=1 (p为质数)522mod23=1mod23=112.选CT(n)=T(n−1)+T(n−2) ,所以复杂度是O(Fn) 。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
scanf("%d",&judge);
if(judge==1){ //自行输入数据
printf("输入%d个整数:",N);
for(i=0;i<N;i++)
scanf("%d",&A[i]);
}
else{
printf("随机产生的%d个整数为:\n",N); //用随机种子随机产生N个0-999的整数
A[i]=rand()%1000;
else
A[i]=(-1)*rand()%1000;
printf("%d\t",A[i]);
}
}
QueryPerformanceCounter(&begin);//记录算法4开始时间
MaxSum=MaxSubsequenceSum(A,N);
QueryPerformanceCounter(&end); //记录算法4终止时间
#include<stdio.h>
#include <time.h>
#include <windows.h>
int MaxSubsequenceSum(int A[],int N);
main()
{
int i,N,*A,MaxSum,judge;
LARGE_INTEGER begin,end,frequency; //代表64位有符号整数,记录程序运行时间
system("pause");
}
int MaxSubsequenceSum(int A[],int N)
{
int ThisSum,MaxSum=0,i,j,k; //对最大值初始化
for(i=0;i<N;i++) //从A[i]开始
for(j=i;j<N;j++){ //以A[j]结束
ThisSum=0;
srand(time(0));
for (i=0;i<N;i++){
if(rand()%2==0) //利用随机数奇偶性的等概率使得正负数约各占一半
A[i]=rand()%1000;
else
A[i]=(-1)*rand()%1000;
printf("%d\t",A[i]);
}
}
QueryPerformanceCounter(&begin);//记录算法3开始时间
分治法求最大子段和问题
共有四种方法:
算法一;
算法二;
算法三、Divide and Conquer
算法四源代码、On-line Algorithm
算法一源代码:
/*Given (possibly negative) integers A1, A2,…, AN, find the maximum value.找最大子段和*/
rights+=a[i];
if(rights>=s2) s2=rights;
}
sum=s1+s2;
if(sum<leftsum) //最大值更新
sum=leftsum;
if(sum<rightsum)
sum=rightsum;
}
return sum;
}
算法四源代码:On-line Algorithm
main()
{
int i,N,*A,MaxSum,judge;
LARGE_INTEGER begin,end,frequency; //代表64位有符号整数,记录程序运行时间
QueryPerformanceFrequency(&frequency);//可以获得当前的处理器的频率
printf("输入整数的个数:");
QueryPerformanceFrequency(&frequency);//可以获得当前的处理器的频率
printf("输入整数的个数:");
scanf("%d",&N);
A=(int *)malloc(N*sizeof(int)); //用数组给数据动态分配空间
printf("自行输入数据请按1,随机产生数据请按2\n");
srand(time(0));
for (i=0;i<N;i++){
if(rand()%2==0) //利用随机数奇偶性的等概率使得正负数约各占一半
A[i]=rand()%1000;
else
A[i]=(-1)*rand()%1000;
printf("%d\t",A[i]);
}
}
QueryPerformanceCounter(&begin);//记录算法1开始时间
for(k=i;k<=j;k++)
ThisSum+=A[k]; //从A[i]到A[j]求和
if(ThisSum>MaxSum)
MaxSum=ThisSum; //更新最大值
}
return MaxSum;
}
算法2源代码:
/*Given (possibly negative) integers A1, A2,…, AN, find the maximum value.找最大子段和*/
printf("\n最大子段和为:%d\n",MaxSum);
printf("算法4运行时间为:%f seconds\n",(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart);//终止时间-开始时间=算法1运行时间
QueryPerformanceFrequency(&frequency);//可以获得当前的处理器的频率
printf("输入整数的个数:");
scanf("%d",&N);
A=(int *)malloc(N*sizeof(int)); //用数组给数据动态分配空间
printf("自行输入数据请按1,随机产生数据请按2\n");
/*Given (possibly negative) integers A1, A2,…, AN, find the maximum value.找最大子段和*/
#include<stdio.h>
#include <time.h>
#include <windows.h>
int MaxSubsequenceSum(int A[],int N);
MaxSum=MaxSubsequenceSum(A,N);
QueryPerformanceCounter(&end); //记录算法1终止时间
printf("\n最大子段和为:%d\n",MaxSum);
printf("算法1运行时间为:%f seconds\n",(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart);//终止时间-开始时间=算法1运行时间
#include<stdio.h>
#include <time.h>
#include <windows.h>
int MaxSubsequenceSum(int A[],int N);
main()
{
int i,N,*A,MaxSum,judge;
LARGE_INTEGER begin,end,frequency; //代表64位有符号整数,记录程序运行时间
QueryPerformanceFrequency(&frequency);//可以获得当前的处理器的频率
printf("输入整数的个数:");
scanf("%d",&N);
A=(int *)malloc(N*sizeof(int)); //用数组给数据动态分配空间
printf("自行输入数据请按1,随机产生数据请按2\n");
system("pause");
}
int MaxSubsequenceSum(int A[],int N)
{
int ThisSum,MaxSum=0,i,j; //对最大值初始化
for(i=0;i<N;i++){ //从A[i]开始
ThisSum=0;
for(j=i;j<N;j++){ //以A[j]结束
system("pause");
}
int Divide_Conquer(int a[],int left,int right)//分治算法
{
int sum=0,leftsum=0,rightsum=0,center,i;
if(left==right){
if(a[left]>0)
sum=a[left];
ThisSum+=A[j]; //从A[i]到A[j]求和
if(ThisSum>MaxSum)
MaxSum=ThisSum; //更新最大值
}
}
return MaxSum;
}
算法三源代码:分治法
/*Given (possibly negative) integers A1, A2,…, AN, find the maximum value.找最大子段和*/
相关文档
最新文档