算法设计与分析报告
- 格式:doc
- 大小:56.50 KB
- 文档页数:10
算法设计与分析实验报告一实验名称统计数字问题评分实验日期2014 年11 月15 日指导教师姓名专业班级学号一.实验要求1、掌握算法的计算复杂性概念。
2、掌握算法渐近复杂性的数学表述。
3、掌握用C++语言描述算法的方法。
4.实现具体的编程与上机实验,验证算法的时间复杂性函数。
二.实验内容统计数字问题1、问题描述一本书的页码从自然数1 开始顺序编码直到自然数n。
书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。
例如,第6 页用数字6 表示,而不是06 或006 等。
数字计数问题要求对给定书的总页码n,计算出书的全部页码中分别用到多少次数字0,1,2, (9)2、编程任务给定表示书的总页码的10 进制整数n (1≤n≤109) 。
编程计算书的全部页码中分别用到多少次数字0,1,2, (9)三.程序算法将页码数除以10,得到一个整数商和余数,商就代表页码数减余数外有多少个1—9作为个位数,余数代表有1—余数本身这么多个数作为剩余的个位数,此外,商还代表1—商本身这些数出现了10次,余数还代表剩余的没有计算的商的大小的数的个数。
把这些结果统计起来即可。
四.程序代码#include<iostream.h>int s[10]; //记录0~9出现的次数int a[10]; //a[i]记录n位数的规律void sum(int n,int l,int m){ if(m==1){int zero=1;for(int i=0;i<=l;i++) //去除前缀0{ s[0]-=zero;zero*=10;} }if(n<10){for(int i=0;i<=n;i++){ s[i]+=1; }return;}//位数为1位时,出现次数加1//位数大于1时的出现次数for(int t=1;t<=l;t++)//计算规律f(n)=n*10^(n-1){m=1;int i;for(i=1;i<t;i++)m=m*10;a[t]=t*m;}int zero=1;for(int i=0;i<l;i++){ zero*= 10;} //求出输入数为10的n次方int yushu=n%zero; //求出最高位以后的数int zuigao=n/zero; //求出最高位zuigaofor(i=0;i<zuigao;i++){ s[i]+=zero;} //求出0~zuigao-1位的数的出现次数for(i=0;i<10;i++){ s[i]+=zuigao*a[l];} //求出与余数位数相同的0~zuigao-1位中0~9出现的次数//如果余数是0,则程序可结束,不为0则补上所缺的0数,和最高位对应所缺的数if(yushu==0) //补上所缺的0数,并且最高位加1{ s[zuigao]++;s[0]+=l; }else{ i=0;while((zero/=10)>yushu){ i++; }s[0]+=i*(yushu+1);//补回因作模操作丢失的0s[zuigao]+=(yushu+1);//补回最高位丢失的数目sum(yushu,l-i-1,m+1);//处理余位数}}void main(){ int i,m,n,N,l;cout<<"输入数字要查询的数字:";cin>>N;cout<<'\n';n = N;for(i=0;n>=10;i++){ n/=10; } //求出N的位数n-1l=i;sum(N,l,1);for(i=0; i<10;i++){ cout<< "数字"<<i<<"出现了:"<<s[i]<<"次"<<'\n'; }}五.程序调试中的问题调试过程,页码出现报错。
《算法设计与分析》实验报告实验一递归与分治策略应用基础学号:**************姓名:*************班级:*************日期:2014-2015学年第1学期第九周一、实验目的1、理解递归的概念和分治法的基本思想2、了解适用递归与分治策略的问题类型,并能设计相应的分治策略算法3、掌握递归与分治算法时间空间复杂度分析,以及问题复杂性分析方法二、实验内容任务:以下题目要求应用递归与分治策略设计解决方案,本次实验成绩按百分制计,完成各小题的得分如下,每小题要求算法描述准确且程序运行正确。
1、求n个元素的全排。
(30分)2、解决一个2k*2k的特殊棋牌上的L型骨牌覆盖问题。
(30分)3、设有n=2k个运动员要进行网球循环赛。
设计一个满足要求的比赛日程表。
(40分)提交结果:算法设计分析思路、源代码及其分析说明和测试运行报告。
三、设计分析四、算法描述及程序五、测试与分析六、实验总结与体会#include "iostream"using namespace std;#define N 100void Perm(int* list, int k, int m){if (k == m){for (int i=0; i<m; i++)cout << list[i] << " ";cout << endl;return;}else{for (int i=m; i<k; i++){swap(list[m], list[i]);Perm(list, k, m+1);swap(list[m], list[i]);}}}void swap(int a,int b){int temp;temp=a;a=b;b=temp;}int main(){int i,n;int a[N];cout<<"请输入排列数据总个数:";cin>>n;cout<<"请输入数据:";for(i=0;i<n;i++){cin>>a[i];}cout<<"该数据的全排列:"<<endl;Perm(a,n,0);return 0;}《算法设计与分析》实验报告实验二递归与分治策略应用提高学号:**************姓名:*************班级:*************日期:2014-2015学年第1学期一、实验目的1、深入理解递归的概念和分治法的基本思想2、正确使用递归与分治策略设计相应的问题的算法3、掌握递归与分治算法时间空间复杂度分析,以及问题复杂性分析方法二、实验内容任务:从以下题目中任选一题完成,要求应用递归与分治策略设计解决方案。
第1篇一、实验背景与目的随着计算机技术的飞速发展,算法在计算机科学中扮演着至关重要的角色。
为了加深对算法设计与分析的理解,提高实际应用能力,本实验课程设计旨在通过实际操作,让学生掌握算法设计与分析的基本方法,学会运用所学知识解决实际问题。
二、实验内容与步骤本次实验共分为三个部分,分别为排序算法、贪心算法和动态规划算法的设计与实现。
1. 排序算法(1)实验目的:熟悉常见的排序算法,理解其原理,比较其优缺点,并实现至少三种排序算法。
(2)实验内容:- 实现冒泡排序、快速排序和归并排序三种算法。
- 对每种算法进行时间复杂度和空间复杂度的分析。
- 编写测试程序,对算法进行性能测试,比较不同算法的优劣。
(3)实验步骤:- 分析冒泡排序、快速排序和归并排序的原理。
- 编写三种排序算法的代码。
- 分析代码的时间复杂度和空间复杂度。
- 编写测试程序,生成随机测试数据,测试三种算法的性能。
- 比较三种算法的运行时间和内存占用。
2. 贪心算法(1)实验目的:理解贪心算法的基本思想,掌握贪心算法的解题步骤,并实现一个贪心算法问题。
(2)实验内容:- 实现一个贪心算法问题,如活动选择问题。
- 分析贪心算法的正确性,并证明其最优性。
(3)实验步骤:- 分析活动选择问题的贪心策略。
- 编写贪心算法的代码。
- 分析贪心算法的正确性,并证明其最优性。
- 编写测试程序,验证贪心算法的正确性。
3. 动态规划算法(1)实验目的:理解动态规划算法的基本思想,掌握动态规划算法的解题步骤,并实现一个动态规划算法问题。
(2)实验内容:- 实现一个动态规划算法问题,如背包问题。
- 分析动态规划算法的正确性,并证明其最优性。
(3)实验步骤:- 分析背包问题的动态规划策略。
- 编写动态规划算法的代码。
- 分析动态规划算法的正确性,并证明其最优性。
- 编写测试程序,验证动态规划算法的正确性。
三、实验结果与分析1. 排序算法实验结果:- 冒泡排序:时间复杂度O(n^2),空间复杂度O(1)。
算法分析与设计实验报告算法分析与设计实验报告一、引言算法是计算机科学的核心,它们是解决问题的有效工具。
算法分析与设计是计算机科学中的重要课题,通过对算法的分析与设计,我们可以优化计算机程序的效率,提高计算机系统的性能。
本实验报告旨在介绍算法分析与设计的基本概念和方法,并通过实验验证这些方法的有效性。
二、算法分析算法分析是评估算法性能的过程。
在实际应用中,我们常常需要比较不同算法的效率和资源消耗,以选择最适合的算法。
常用的算法分析方法包括时间复杂度和空间复杂度。
1. 时间复杂度时间复杂度衡量了算法执行所需的时间。
通常用大O表示法表示时间复杂度,表示算法的最坏情况下的运行时间。
常见的时间复杂度有O(1)、O(log n)、O(n)、O(n log n)和O(n^2)等。
其中,O(1)表示常数时间复杂度,O(log n)表示对数时间复杂度,O(n)表示线性时间复杂度,O(n log n)表示线性对数时间复杂度,O(n^2)表示平方时间复杂度。
2. 空间复杂度空间复杂度衡量了算法执行所需的存储空间。
通常用大O表示法表示空间复杂度,表示算法所需的额外存储空间。
常见的空间复杂度有O(1)、O(n)和O(n^2)等。
其中,O(1)表示常数空间复杂度,O(n)表示线性空间复杂度,O(n^2)表示平方空间复杂度。
三、算法设计算法设计是构思和实现算法的过程。
好的算法设计能够提高算法的效率和可靠性。
常用的算法设计方法包括贪心算法、动态规划、分治法和回溯法等。
1. 贪心算法贪心算法是一种简单而高效的算法设计方法。
它通过每一步选择局部最优解,最终得到全局最优解。
贪心算法的时间复杂度通常较低,但不能保证得到最优解。
2. 动态规划动态规划是一种将问题分解为子问题并以自底向上的方式求解的算法设计方法。
它通过保存子问题的解,避免重复计算,提高算法的效率。
动态规划适用于具有重叠子问题和最优子结构的问题。
3. 分治法分治法是一种将问题分解为更小规模的子问题并以递归的方式求解的算法设计方法。
算法与分析实验报告一、引言算法是现代计算机科学中的核心概念,通过合理设计的算法可以解决复杂的问题,并提高计算机程序的执行效率。
本次实验旨在通过实际操作和数据统计,对比分析不同算法的执行效率,探究不同算法对于解决特定问题的适用性和优劣之处。
二、实验内容本次实验涉及两个经典的算法问题:排序和搜索。
具体实验内容如下:1. 排序算法- 冒泡排序- 插入排序- 快速排序2. 搜索算法- 顺序搜索- 二分搜索为了对比不同算法的执行效率,我们需要设计合适的测试用例并记录程序执行时间进行比较。
实验中,我们将使用随机生成的整数数组作为排序和搜索的测试数据,并统计执行时间。
三、实验步骤1. 算法实现与优化- 实现冒泡排序、插入排序和快速排序算法,并对算法进行优化,提高执行效率。
- 实现顺序搜索和二分搜索算法。
2. 数据生成- 设计随机整数数组生成函数,生成不同大小的测试数据。
3. 实验设计- 设计实验方案,包括测试数据的规模、重复次数等。
4. 实验执行与数据收集- 使用不同算法对随机整数数组进行排序和搜索操作,记录执行时间。
- 多次重复同样的操作,取平均值以减小误差。
5. 数据分析与结果展示- 将实验收集到的数据进行分析,并展示在数据表格或图表中。
四、实验结果根据实验数据的收集与分析,我们得到以下结果:1. 排序算法的比较- 冒泡排序:平均执行时间较长,不适用于大规模数据排序。
- 插入排序:执行效率一般,在中等规模数据排序中表现良好。
- 快速排序:执行效率最高,适用于大规模数据排序。
2. 搜索算法的比较- 顺序搜索:执行时间与数据规模成线性关系,适用于小规模数据搜索。
- 二分搜索:执行时间与数据规模呈对数关系,适用于大规模有序数据搜索。
实验结果表明,不同算法适用于不同规模和类型的问题。
正确选择和使用算法可以显著提高程序的执行效率和性能。
五、实验总结通过本次实验,我们深入了解了不同算法的原理和特点,并通过实际操作和数据分析对算法进行了比较和评估。
算法设计与分析实验报告算法设计与分析实验报告引言:算法设计与分析是计算机科学中的重要课程,它旨在培养学生解决实际问题的能力。
本次实验旨在通过设计和分析不同类型的算法,加深对算法的理解,并探索其在实际应用中的效果。
一、实验背景算法是解决问题的步骤和方法的描述,是计算机程序的核心。
在本次实验中,我们将重点研究几种经典的算法,包括贪心算法、动态规划算法和分治算法。
通过对这些算法的设计和分析,我们可以更好地理解它们的原理和应用场景。
二、贪心算法贪心算法是一种基于局部最优选择的算法,它每一步都选择当前状态下的最优解,最终得到全局最优解。
在实验中,我们以背包问题为例,通过贪心算法求解背包能够装下的最大价值物品。
我们首先将物品按照单位重量的价值从大到小排序,然后依次将能够装入背包的物品放入,直到背包无法再装下物品为止。
三、动态规划算法动态规划算法是一种通过将问题分解为子问题,并记录子问题的解来求解整体问题的算法。
在实验中,我们以斐波那契数列为例,通过动态规划算法计算斐波那契数列的第n项。
我们定义一个数组来保存已经计算过的斐波那契数列的值,然后通过递推公式将前两项的值相加得到后一项的值,最终得到第n项的值。
四、分治算法分治算法是一种将问题分解为更小的子问题,并通过递归求解子问题的算法。
在实验中,我们以归并排序为例,通过分治算法对一个无序数组进行排序。
我们首先将数组分成两个子数组,然后对子数组进行递归排序,最后将两个有序的子数组合并成一个有序的数组。
五、实验结果与分析通过对以上三种算法的设计和分析,我们得到了以下实验结果。
在贪心算法中,我们发现该算法能够在有限的时间内得到一个近似最优解,但并不能保证一定得到全局最优解。
在动态规划算法中,我们发现该算法能够通过记忆化搜索的方式得到准确的结果,但在问题规模较大时,其时间复杂度较高。
在分治算法中,我们发现该算法能够将问题分解为更小的子问题,并通过递归求解子问题,最终得到整体问题的解。
算法设计与分析报告在当今数字化的时代,算法无处不在,从我们日常使用的智能手机应用到复杂的科学研究和金融交易系统,都离不开算法的支持。
算法设计与分析作为计算机科学的核心领域之一,对于提高计算效率、优化资源利用以及解决实际问题具有至关重要的意义。
算法,简单来说,就是为解决特定问题而制定的一系列清晰、准确的步骤。
一个好的算法不仅要能够正确地解决问题,还需要在时间和空间复杂度上尽可能地高效。
这就要求我们在设计算法时,充分考虑问题的特点和约束条件,选择最合适的算法策略。
在算法设计的过程中,首先要对问题进行深入的理解和分析。
明确问题的输入和输出,以及所期望达到的目标。
例如,在排序问题中,我们需要将一组无序的数据按照一定的顺序排列。
常见的排序算法有冒泡排序、插入排序、选择排序、快速排序等。
对于较小规模的数据,冒泡排序和插入排序可能是简单而有效的选择;而对于大规模的数据,快速排序通常能够提供更好的性能。
接下来,我们要根据问题的特点和要求选择合适的算法策略。
算法策略可以大致分为贪心算法、分治算法、动态规划、回溯算法等。
贪心算法通过在每一步都做出当前看起来最优的选择来逐步逼近最终的解,但并不一定能得到全局最优解。
分治算法则是将一个大问题分解为若干个规模较小且相互独立的子问题,分别求解这些子问题,然后将子问题的解合并得到原问题的解。
动态规划通过保存已解决子问题的结果,避免重复计算,从而有效地解决具有重叠子问题的优化问题。
回溯算法则是一种通过尝试逐步构建解,如果发现当前构建的解不满足条件就回溯并重新尝试的方法。
以背包问题为例,如果我们要在有限的背包容量内选择一些物品,使得物品的总价值最大,就可以使用贪心算法或者动态规划来解决。
贪心算法可能会在某些情况下得到次优解,而动态规划则可以保证得到最优解,但在实现上相对复杂一些。
在算法的实现过程中,数据结构的选择也非常重要。
数据结构是组织和存储数据的方式,不同的数据结构适用于不同的算法和操作。
算法设计与分析实验报告实验一全排列、快速排序【实验目的】1. 掌握全排列的递归算法。
2. 了解快速排序的分治算法思想。
【实验原理】一、全排列全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来。
任何n个字符集的排列都可以与1~n的n个数字的排列一一对应,因此在此就以n 个数字的排列为例说明排列的生成法。
n个字符的全体排列之间存在一个确定的线性顺序关系。
所有的排列中除最后一个排列外,都有一个后继;除第一个排列外,都有一个前驱。
每个排列的后继都可以从它的前驱经过最少的变化而得到,全排列的生成算法就是从第一个排列开始逐个生成所有的排列的方法。
二、快速排序快速排序(Quicksort)是对冒泡排序的一种改进。
它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
【实验内容】1.全排列递归算法的实现。
2.快速排序分治算法的实现。
【实验结果】1. 全排列:2. 快速排序:实验二最长公共子序列、活动安排问题【实验目的】1. 了解动态规划算法设计思想,运用动态规划算法实现最长公共子序列问题。
2. 了解贪心算法思想,运用贪心算法设计思想实现活动安排问题。
【实验原理】一、动态规划法解最长公共子序列设序列X=和Y=的一个最长公共子序列Z=,则:i. 若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;ii. 若xm≠yn且zk≠xm ,则Z是Xm-1和Y的最长公共子序列;iii. 若xm≠yn且z k≠yn ,则Z是X和Yn-1的最长公共子序列。
其中Xm-1=,Yn-1=,Zk-1=。
最长公共子序列问题具有最优子结构性质。
由最长公共子序列问题的最优子结构性质可知,要找出X=和Y=的最长公共子序列,可按以下方式递归地进行:当xm=yn时,找出Xm-1和Yn-1的最长公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一个最长公共子序列。
实验一找最大和最小元素与归并分类算法实现(用分治法)一、实验目的1.掌握能用分治法求解的问题应满足的条件;2.加深对分治法算法设计方法的理解与应用;3.锻炼学生对程序跟踪调试能力;4.通过本次实验的练习培养学生应用所学知识解决实际问题的能力。
二、实验内容1、找最大和最小元素输入n 个数,找出最大和最小数的问题。
2、归并分类将一个含有n个元素的集合,按非降的次序分类(排序)。
三、实验要求(1)用分治法求解问题(2)上机实现所设计的算法;四、实验过程设计(算法设计过程)1、找最大和最小元素采用分治法,将数组不断划分,进行递归。
递归结束的条件为划分到最后若为一个元素则max和min都是这个元素,若为两个取大值赋给max,小值给min。
否则就继续进行划分,找到两个子问题的最大和最小值后,比较这两个最大值和最小值找到解。
2、归并分类使用分治的策略来将一个待排序的数组分成两个子数组,然后递归地对子数组进行排序,最后将排序好的子数组合并成一个有序的数组。
在合并过程中,比较两个子数组的首个元素,将较小的元素放入辅助数组,并指针向后移动,直到将所有元素都合并到辅助数组中。
五、源代码1、找最大和最小元素#include<iostream>using namespace std;void MAXMIN(int num[], int left, int right, int& fmax, int& fmin); int main() {int n;int left=0, right;int fmax, fmin;int num[100];cout<<"请输入数字个数:";cin >> n;right = n-1;cout << "输入数字:";for (int i = 0; i < n; i++) {cin >> num[i];}MAXMIN(num, left, right, fmax, fmin);cout << "最大值为:";cout << fmax << endl;cout << "最小值为:";cout << fmin << endl;return 0;}void MAXMIN(int num[], int left, int right, int& fmax, int& fmin) { int mid;int lmax, lmin;int rmax, rmin;if (left == right) {fmax = num[left];fmin = num[left];}else if (right - left == 1) {if (num[right] > num[left]) {fmax = num[right];fmin = num[left];}else {fmax = num[left];fmin = num[right];}}else {mid = left + (right - left) / 2;MAXMIN(num, left, mid, lmax, lmin);MAXMIN(num, mid+1, right, rmax, rmin);fmax = max(lmax, rmax);fmin = min(lmin, rmin);}}2、归并分类#include<iostream>using namespace std;int num[100];int n;void merge(int left, int mid, int right) { int a[100];int i, j,k,m;i = left;j = mid+1;k = left;while (i <= mid && j <= right) {if (num[i] < num[j]) {a[k] = num[i++];}else {a[k] = num[j++];}k++;}if (i <= mid) {for (m = i; m <= mid; m++) {a[k++] = num[i++];}}else {for (m = j; m <= right; m++) {a[k++] = num[j++];}}for (i = left; i <= right; i++) { num[i] = a[i];}}void mergesort(int left, int right) { int mid;if (left < right) {mid = left + (right - left) / 2;mergesort(left, mid);mergesort(mid + 1, right);merge(left, mid, right);}}int main() {int left=0,right;int i;cout << "请输入数字个数:";cin >> n;right = n - 1;cout << "输入数字:";for (i = 0; i < n; i++) {cin >> num[i];}mergesort(left,right);for (i = 0; i < n; i++) {cout<< num[i];}return 0;}六、运行结果和算法复杂度分析1、找最大和最小元素图1-1 找最大和最小元素结果算法复杂度为O(logn)2、归并分类图1-2 归并分类结果算法复杂度为O(nlogn)实验二背包问题和最小生成树算法实现(用贪心法)一、实验目的1.掌握能用贪心法求解的问题应满足的条件;2.加深对贪心法算法设计方法的理解与应用;3.锻炼学生对程序跟踪调试能力;4.通过本次实验的练习培养学生应用所学知识解决实际问题的能力。
算法设计与分析报告学生姓名学号专业班级指导教师完成时间目录一、课程内容 (3)二、算法分析 (3)1、分治法 (3)(1)分治法核心思想 (3)(2)MaxMin算法分析 (3)2、动态规划 (4)(1)动态规划核心思想 (4)(2)矩阵连乘算法分析 (5)3、贪心法 (5)(1)贪心法核心思想 (5)(2)背包问题算法分析 (6)(3)装载问题算法分析 (7)4、回溯法 (7)(1)回溯法核心思想 (7)(2)N皇后问题非递归算法分析 (7)(3)N皇后问题递归算法分析 (8)三、例子说明 (9)1、MaxMin问题 (9)2、矩阵连乘 (10)3、背包问题 (10)4、最优装载 (10)5、N皇后问题(非递归) (11)6、N皇后问题(递归) (11)四、心得体会 (12)五、算法对应的例子代码 (12)1、求最大值最小值 (12)2、矩阵连乘问题 (13)3、背包问题 (15)4、装载问题 (17)5、N皇后问题(非递归) (19)6、N皇后问题(递归) (20)一、课程内容1、分治法,求最大值最小值,maxmin算法;2、动态规划,矩阵连乘,求最少连乘次数;3、贪心法,1)背包问题,2)装载问题;4、回溯法,N皇后问题的循环结构算法和递归结构算法。
二、算法分析1、分治法(1)分治法核心思想当要求解一个输入规模为n,且n的取值相当大的问题时,直接求解往往是非常困难的。
如果问题可以将n个输入分成k个不同子集合,得到k个不同的可独立求解的子问题,其中1<k≤n, 而且子问题与原问题性质相同,原问题的解可由这些子问题的解合并得出。
那末,这类问题可以用分治法求解。
分治法的核心技术1)子问题的划分技术.2)递归技术。
反复使用分治策略将这些子问题分成更小的同类型子问题,直至产生出不用进一步细分就可求解的子问题。
3)合并技术.(2)MaxMin算法分析问题:在含有n个不同元素的集合中同时找出它的最大和最小元素。
算法设计与分析报告◎小组成员:陈壮茂,陈振凯,张建龙,莫媚,林晓丹◎报告内容:1.给定数组a[0:n-1],试设计一个算法,在最坏情况下用n+[logn]-2次比较找出a[0:n-1] 中的元素的最大值和次大值.◎分析:a[0:n-1] 是说这个数组有n个元素,序号为0到n-1 n+[logn]-2就是一个算法复杂度,应该是n+logn的整数部分-2。
◎首先对数组相邻的两个进行比较,将大的放在后面,小的放在前面,然后在两个数中小的所有数选出最小,同时也在两个数中大的所有数选出最大的。
可以得出总的比较次数:(int)(n/2)+2*((int)(n/2)-1).◎代码如下:#include<iostream.h>#define N 9int k=0;int max(int num[],int n){int big[N],i;cout<<"max"<<endl;for(i=0;2*i<=n-2;i++){if(k++,num[i]>num[n-i-1])big[i]=num[i];elsebig[i]=num[n-i-1];}if(n%2!=0){big[i]=num[i];i++;}if(i==1)return big[0];elsereturn max(big,i);}int fun(int &second,int num[],int n){int big[N],small[N],i,number;第1页cout<<"fun"<<endl;for(i=0;2*i<=n-2;i++){if(k++,num[i]>num[n-i-1]){big[i]=num[i];small[i]=num[n-i-1];}else{big[i]=num[n-i-1];small[i]=num[i];}}if(n%2){big[i]=num[i];i++;}number=max(small,i);second=second>number? second:number;k++;if(i==1)return big[0];elsereturn fun(second,big,i);}void main(){int num[N],second,i,large;cout<<"请输入"<<N<<"个数"<<endl;for(i=0;i<N;i++)cin>>num[i];second=num[0]>num[1]? num[1]:num[0];k++;large=fun(second,num,N);cout<<"最大值是:"<<large<<endl<<"次大值是:"<<second<<endl<<"其中比较次数为:"<<k<<endl;}◎最初数据第2页◎运行过程中的数据变化与结果2.求数列的最大子段和(要求时间复杂为nlogn)◎分析:给出n个整数(亦正亦负)组成的序列a[1],a[2],a[3],…,a[n],求该序列中a[i]+a[i+1]+…+a[j]的子段和的最大值。
当最大子段和为负数时,规定此数列的最大子段和为0. ◎算法和思路: 依据上面的描述,所求的点i最大路径和c[i]应该为:Max{a[i], c[i - 1] + a[i]}int maxSubSum(int P[]){ int i;int maxsum = 0;int c = 0;for(i = 0; i < MAX; i++){if(c > 0)c += P[i];elsec = P[i];if(c > maxsum)maxsum = c;}return maxsum;}◎主函数:int main(){ int A[MAX];int i,sum;printf("Please input a array: ");for(i = 0; i < MAX; i++)scanf("%d",&A[i]);sum = maxSubSum(A);printf(" The Max subsum is: %d",sum);第3页return 0;}◎当输入数据为:8, 4, -1, 14◎运行过程:c=8+4=12(C=8+4-1)<12(和会下降,于是不能赋值给maxsum)(C=8+4-1+14)>12(和又上升了,赋值给了C值)3.设计一个O(n*n)时间的算法,找出由n个数组成的序列最长单调递增子序列.◎分析:(1)递推关系①对a(n)来说,由于它是最后一个数,所以当a(n)从开始查找时,只存在长度为1的不下降序列。
②若从a(n-1)开始查找,则存在下面两种可能性:若a(n-1)<a(n),则存在长度为的不下降序列。
若a(n-1)>a(n) ,则存在长度为的不下降序列。
③若从a(i)开始,此时最长不下降序列应该按下列方法求出:在a(i+1),a(i+2),…,a(n)中,找出一个起始数据比a(i)大且最长的不下降序列,作为它的后续。
(2)数据结构设计用数组b[i]记录点i到得最长的不下降子序列的长度,记录点i在最长的不下降子序列的后继续数据编号。
◎算法如下:Int maxn=100;Int a[maxn],b[maxn],c[maxn];Main(){int n,I,j,max,p;input(n);for(i=1;i<=n;i=i+1){input(a[i]);b[i]=1;c[i]=0;}For(i=n-1;i>=1;i=i-1){max=0;p=0;for(j=i+1;j<=n;j=j+1)if(a[i]<a[j] and b[j]>max){max=b[j];p=j;}if(p<>0){b[i]=b[p]+1;c[i]=p;}}Max=0;p=0;For(i=1;i<=n;i++)if(b[i]>max)第4页{max=b[i];p=I;}Print(“maxlong=“,max);Print(“result is:”);While(p<>0){print(a[p]);p=c[p];}}◎经过循环,数据的变化a[1] =3; a[2]=18; a[3]=7b[1] =1; b[2]= 1; b[3]=1c[1] =0; c[2]= 0; c[3]=0◎变化结果:a[1] =3; a[2]=18; a[3]=7b[1] =2; b[2]= 1; b[3]=1c[1] =2; c[2]= 0; c[3]= 04.礼物分配问题. 两兄弟Alan 和Bob, 共同分配n个礼物. 每个礼物只能分给其中的一个人,且不能分成两个.每个礼物i 的价值为vi, 为正整数.设 a 和 b 分别表示Alan 和 Bob所收到的礼物的总价值, V=baVnii+=∑=1, 为所有礼物的总价值. 为使两兄弟高兴,我们希望尽可能地均分这些礼物, 即 |a-b| 打到最小。
◎分析:该题目要求使得所分的礼物差值最小;首先,我们知道礼物总价值为V=baVnii+=∑=1;由于要使差值最小,则a与b要最接近于1/2V;故可以设a=1/2V+t,b=1/2V-t;故|a-b|=|(1/2V+t)-(1/2V-t)|=2t;而t=a-1/2V;其中V为已知,则只要a为大于1/2V的最小数即可。
依照次数学思路,我们可以将该方法进行具体话:既是将数组降序排列(这一点很重要,可以用数学分析法进行证明),然后将数组的一个元素赋给a,如果a加上该元素后大于b,则将下一个元素赋给b,循环进行判断直至数组结束。
数学证明过程略◎代码如下:#include<iostream>using namespace std;#define MaxSize 50voidcollat(int n,int v){int a=0;int b=0;第5页int Alan[MaxSize]={0},Bob[MaxSize]={0},r=0,s=0;for(int i=n;i>0;i--){if(a>b){b=b+v*i;Bob[r]=v*i;r++;}else{a=a+v*i;Alan[s]=v*i;s++;}}cout<<"Alan分配到的礼物为:"<<endl;for(int j=0;j<r;j++){cout<<Alan[j]<<" ";}cout<<endl;cout<<"Bob分配到的礼物为:"<<endl;for(int k=0;k<r;k++){cout<<Bob[k]<<" ";}cout<<endl;cout<<"Alan分配到的礼物总价值为:"<<a<<endl;第6页cout<<"Bob分配到的礼物总价值为:"<<b<<endl;}int main(){int num,v;cout<<"请输入礼物的个数:";cin>>num;cout<<"请输入单位礼物的价值:";cin>>v;collat(num,v);return 0;}7.键盘输入一个高精度的正整数N, 去掉其中任意S个数字后剩下的数字按左右次序将组成一个新的正整数.编程对给定的N和S,寻找一种方案使得剩下的数字组成的新数最小.◎代码如下:#include<iostream>using namespace std;#define MaxSize 50#define T 10void OrderArray(int N,int S){int array[MaxSize]={0};int i=0,j,a=N,max,tag;while(N>=10){array[i]=N%10;N=N/10;i++; }array[i]=N;for(j=0;j<S;j++){for(int p=i;p>=0;p--)第7页{if(array[p]>array[p-1]){for(int s=p;s<=i;s++)array[s]=array[s+1];i--;break;}}}for(int r=i;r>=0;r--)cout<<array[r];}int main(){OrderArray(12435863,2);return 0;}8.最佳调度问题。