ImageVerifierCode 换一换
你正在下载:

算法.docx

[预览]
格式:DOCX , 页数:22 ,大小:42.77KB ,
资源ID:11085313      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11085313.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(算法.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

算法.docx

1、算法知道为什么计算机能高效准确的帮助我们解决复杂的问题吗?你可能会回答因为它是电脑呀,但实际上真正的原因是因为我们给它注入了我们人类的解决问题的思路,否则它也是什么事情也不能做的哟。在前面我们学习了给计算机注入我们思路的工具C语言,下面我们就来学习一些高效的解决问题的思路第6章 常用算法【教学提示】从给定的问题入手,先想想其解决思路,再试着将思路用书面的形式表述出来,然后用C语言让计算机求解该问题,最后想想在现实生活当中还有什么问题可以用此类思路来解决,从而总结出此思路可解决问题的特性。【教学要求】培养学生逻辑思维能力和推导能力,掌握高效准确的解决较为复杂问题的思路。【主要内容】迭代法,穷举搜

2、索法, 递推法,递归法, 回溯法,贪婪法的解决问题的思路,C语言实现的源代码以及思考。6.1算法概述要使计算机能完成人们预定的工作,首先必须为如何完成预定的工作设计一个算法,然后再根据算法编写程序指令。计算机程序要对问题的每个对象和处理规则给出正确详尽的描述,其中程序的数据结构和变量用来描述问题的对象,程序结构、函数和语句用来描述问题的算法。算法数据结构是程序的两个重要方面。 算法是问题求解过程的精确描述,一个算法由有限条可完全机械地执行的、有确定结果的指令组成。指令正确地描述了要完成的任务和它们被执行的顺序。计算机按算法指令所描述的顺序执行算法的指令能在有限的步骤内终止,或终止于给出问题的解

3、,或终止于指出问题对此输入数据无解。 通常求解一个问题可能会有多种算法可供选择,选择的主要标准是算法的正确性和可靠性,简单性和易理解性。其次是算法所需要的存储空间少和执行更快等。 算法设计是一件非常困难的工作,经常采用的算法设计技术主要有迭代法、穷举搜索法、递推法、贪婪法、回溯法、分治法、动态规划法等等。另外,为了更简洁的形式设计和藐视算法,在算法设计时又常常采用递归技术,用递归描述算法。 6.2 迭代法 迭代法是用于求方程或方程组近似根的一种常用的算法设计方法。设方程为f(x)=0,可采用某种数学方法导出其等价的形式x=g(x),然后按以下步骤执行: (1) 选一个方程的近似根,赋给变量x0

4、; (2) 将x0的值保存于变量x1,然后计算g(x1),并将结果存于变量x0; (3) 当x0与x1的差的绝对值还小于指定的精度要求时,重复步骤(2)的计算。 否则认为x0为原方程的近似根。若方程有根,并且用上述方法计算出来的近似根序列收敛,则按上述方法求得的x0就认为是方程的根。上述算法用C程序的形式表示为: 【算法】迭代法求方程的根 x0=初始近似根; do x1=x0; x0=g(x1); /*按特定的方程计算新的近似根*/ while ( fabs(x0-x1)Epsilon); printf(“方程的近似根是%fn”,x0); 【例6-1】 用迭代法求-2-4x-7=0在3,4的解

5、,要求精度为0.00001。问题分析 按照上面的解题思路,我们先将方程转化为等价的形式x=2+4/x+7/。从题目上看,要求方程在区间3到4的解,则我们不妨可令初始值x0为3.1,然后按照迭代法的思路编制程序如下:main() double x0,x1,epsilon=1e-5; x0 = 3.1; do x1=x0; x0=2+4/x1+7/(x1*x1); /*按特定的方程计算新的近似根*/ while ( fabs(x0-x1)epsilon); printf(“近似根是%.5f”,x1);求的近似值为:3.63199。 想一想迭代公式采用 x=(-2-7)/4行吗?不妨试一试。另外迭代

6、算法也常用于求方程组的根,设方程组为: xi=gi(X) (I=0,1,n-1)令初始值为: X=(x0,x1,xn-1) 则求方程组近似根的迭代算法可描述如下: 【算法】迭代法求方程组的根 for (i=0;i=n-1;i+) xi=初始近似根; do for (i=0;i=n-1;i+) yi=xi; for (i=0;i=n-1;i+) xi=gi(X); for (delta=0.0,i=0;idelta) delta=fabs(yi-xi); while (deltaEpsilon); for (i=0;i=r;i-) for(j=i-1;j=r-1;j-) for(k=j-1;k=

7、1;k-) t= t+1;printf(“%4d%4d%4d”,i,j,k); 想一想假如有n=9,r=5此问题的求解会发生什么变化?知识点播用穷举搜索法解决问题一般都有一个问题,当r变化时,循环重数改变,这就影响了这一问题的解的通用性,即没有一般性。但是,很多情况下穷举搜索法还是常用的。 提醒用穷举搜索法解决问题,最重要的因素就是确定某种方法来确定所有的候选解。下面用一个示例来加以说明。【问题】 背包问题 问题描述 有不同价值、不同重量的物品n件,求从这n件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。 问题分析 设n个物品的重量和价值分别

8、存储于数组w 和v 中,限制重量为tw。考虑一个n元组(x0,x1,xn-1),其中xi=0 表示第i个物品没有选取,而xi=1则表示第i个物品被选取。显然这个n元组等价于一个选择方案。用枚举法解决背包问题,需要枚举所有的选取方案,而根据上述方法,我们只要枚举所有的n元组,就可以得到问题的解。 显然,每个分量取值为0或1的n元组的个数共为2n个。而每个n元组其实对应了一个长度为n的二进制数,且这些二进制数的取值范围为02n-1。因此,如果把02n-1分别转化为相应的二进制数,则可以得到我们所需要的2n个n元组。 【算法】 maxv=0; for (i=0;i2n;i+) B0.n-1=0; 把

9、i转化为二进制数,存储于数组B中; temp_w=0; temp_v=0; for (j=0;j if (Bj=1) temp_w=temp_w+wj; temp_v=temp_v+vj; if (temp_wmaxv) maxv=temp_v; 保存该B数组; 试一试 读者自行将此问题的解决思路用C语言实现。6.4 递推法递推法的解决问题是指在前面已知的一个或几个结果的基础上推导出下一个结果,从而推导出最终解的解决方法。【例6-3】 有一数列,第一个数是2,第二个数是3,第三个是前两个数之和,以后每个数都是其前两个数之和,要求输出该数列的前N(10)项。 问题分析 显然这是一个典型的递推问题

10、,从第三个数开始,每个数都是其前两个数之和,即要想知道第N个数,必须先知道第N-2个和第N-1个数,然后才能求第N个数。这样的问题可以利用循环结构,从已知数开始,循环计算,直到计算出第N个数。此例可以先把已知两个数分别放置到变量A 和B中,显示A和B,再计算C=A+B得到第三个数,输出第三个数C;要得到第四个数,应该把C和B相加,但是为了减少变量的使用和简化程序,我们可以把B的值移到A中(A中原来的数据已经无用),让出B变量,再把C中的数据移到B中,再计算C=A+B,输出C的值,得到第四个数;再把B的值移到A中,如此循环,可以得到数列的N个数。基本算法与程序实现:#define N 10mai

11、n() int i,A=2,B=3,C; C=A+B; printf(“%4dn%4dn”,A,B); for(i=3;i1时)6.6 回溯法回溯法是一个既带有系统性又带有跳跃性的的搜索算法。知识点播 回溯法的基本思想是在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一

12、解时,只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。算法分析1、问题的解空间:应用回溯法解问题时,首先应明确定义问题的解空间。问题的解空间应到少包含问题的一个(最优)解。2、运用回溯法解题通常包含以下三个步骤:(1)针对所给问题,定义问题的解空间;(2)确定易于搜索的解空间结构;(3)以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索;3、递归回溯:由于回溯法是对解空间的深度优先搜索,因此在一般情况下可用递归函数来实现。回溯法基本算法如下: try (int i)if ( in) 输出结果else fo

13、r j =下界 to 上界 xi=hj;if 可行 满足限界函数和约束条件 置值;try(i+1); 说明:i是递归深度; n是深度控制,即解空间树的的高度;可行性判断有两方面的内容:不满约束条件则剪去相应子树;若限界函数越界,也剪去相应子树;两者均满足则进入下一层。【例6-5】采用回溯法找出从自然数1,2,n中任取r个数的所有组合。问题描述 设n=5,r=3,并将找到的组合以从小到大顺序存于a0,a1,ar-1中,组合的元素满足以下性质:(1) ai+1ai,后一个数字比前一个大;(2) ai-i=n-r+1。问题分析 首先放弃组合数个数为r的条件,候选组合从只有一个数字1开始。因该候选解满

14、足除问题规模之外的全部条件,扩大其规模,并使其满足上述条件(1),候选组合改为1,2。继续这一过程,得到候选组合1,2,3。该候选解满足包括问题规模在内的全部条件,因而是一个解。在该解的基础上,选下一个候选解,因a2上的3调整为4,以及以后调整为5都满足问题的全部要求,得到解1,2,4和1,2,5。由于对5不能再作调整,就要从a2回溯到a1,这时,a1=2,可以调整为3,并向前试探,得到解1,3,4。重复上述向前试探和向后回溯,直至要从a0再回溯时,说明已经找完问题的全部解。按上述思想写成程序如下:【程序】# define MAXN 100int aMAXN;void comb(int m,i

15、nt r) int i,j,k; clrscr(); for(i=0;i=r-1;i+) ai=i+1; i=r-1; j=i; do if (ai-i=m-r+1 ) for(k=i+1;k=r-1;k+) ak=ak-1+1; for (k=0;k=r-1;k+) printf(%4d,ak); printf(n); i=r-1; ai+; continue; else i=j; if (i=0) return; a-i+; j=i; while (1);main() comb(7,5); 想一想回溯法与递归法在解决问题的思路上是不是相同的,他们有何区别和联系?6.7 贪婪法贪婪法是一种不

16、追求最优解,只希望得到较为满意解的方法。贪婪法一般可以快速得到满意的解,因为它省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪婪法常以当前情况为基础作最优选择,而不考虑各种可能的整体情况,所以贪婪法不要回溯。知识点播 平时购物找钱时,为使找回的零钱的硬币数最少,不考虑找零钱的所有各种方案,而是从最大面值的币种开始,按递减的顺序考虑各币种,先尽量用大面值的币种,当不足大面值币种的金额时才去考虑下一种较小面值的币种。这就是在使用贪婪法。这种方法在这里总是最优,是因为银行对其发行的硬币种类和硬币面值的巧妙安排。如只有面值分别为1、5和11单位的硬币,而希望找回总额为15单位的硬币。按贪婪算法,

17、应找1个11单位面值的硬币和4个1单位面值的硬币,共找回5个硬币。但最优的解应是3个5单位面值的硬币。【例6-6】 装箱问题问题描述 装箱问题可简述如下:设有编号为0、1、n-1的n种物品,体积分别为v0、v1、vn-1。将这n种物品装到容量都为V的若干箱子里。约定这n种物品的体积均不超过V,即对于0in,有0viV。不同的装箱方案所需要的箱子数目可能不同。装箱问题要求使装尽这n种物品的箱子数要少。问题分析 若考察将n种物品的集合分划成n个或小于n个物品的所有子集,最优解就可以找到。但所有可能划分的总数太大。对适当大的n,找出所有可能的划分要花费的时间是无法承受的。为此,对装箱问题采用非常简单

18、的近似算法,即贪婪法。该算法依次将物品放到它第一个能放进去的箱子中,该算法虽不能保证找到最优解,但还是能找到非常好的解。不失一般性,设n件物品的体积是按从大到小排好序的,即有v0v1vn-1。如不满足上述要求,只要先对这n件物品按它们的体积从大到小排序,然后按排序结果对物品重新编号即可。算法描述: 输入箱子的容积; 输入物品种数n; 按体积从大到小顺序,输入各物品的体积; 预置已用箱子链为空; 预置已用箱子计数器box_count为0;for (i=0;in;i+) 从已用的第一只箱子开始顺序寻找能放入物品i 的箱子j; if (已用箱子都不能再放物品i) 另用一个箱子,并将物品i放入该箱子;

19、 box_count+; else 将物品i放入箱子j; 上述算法能求出需要的箱子数box_count,并能求出各箱子所装物品。下述程序为上述算法的C语言描述。程序描述 每只箱子所装物品用链表来表示,链表首结点指针存于一个结构中,结构记录尚剩余的空间量和该箱子所装物品链表的首指针。另将全部箱子的信息也构成链表。以下是按以上算法编写的程序。【程序】# include # include typedef struct ele int vno; /*存放箱子的编号*/ struct ele *link; /*链表指针*/ ELE;typedef struct hnode int remainder;

20、 /*记录尚剩余的空间量*/ ELE *head; /*该箱子所装物品链表的首指针*/ struct hnode *next; /*指向下一个装有物品的箱子*/ HNODE;void main() int n, i, box_count, box_volume, *a; HNODE *box_h, *box_t, *j; ELE *p, *q; printf(输入箱子容积n); scanf(%d,&box_volume); printf(输入物品种数n); scanf(%d,&n); a=(int *)malloc(sizeof(int)*n); printf(请按体积从大到小顺序输入各物品的

21、体积:); for (i=0;in;i+) scanf(%d,&ai); box_h=box_t=NULL; /*预置已用箱子链为空*/ box_count=0; for (i=0;ivno=i; for (j=box_h;j!=NULL;j=j-next) if (j-remainder=ai) break; if (j=NULL) /*已用箱子都不能再放物品i*/ /*另用一个箱子,并将物品i放入该箱子*/ j=(HNODE *)malloc(sizeof(HNODE); j-remainder=box_volume-ai; j-head=NULL; if (box_h=NULL) box

22、_h=box_t=j; else box_t=box_t-next=j; j-next=NULL; box_count+; else j-remainder -=ai; /*将物品i放入箱子j*/ for (q=j-head;q!=NULL&q-link!=NULL;q=q-link); if (q=NULL) /*新启用的箱子*/ p-link=j-head; j-head=p; else p-link=NULL; q-link=p; printf(共使用了%d只箱子,box_count); printf(各箱子装物品情况如下:); for (j=box_h,i=1;j!=NULL;j=j-

23、next,i+) printf(第%2d只箱子还剩余容积%4d,所装物品有;n,i,j-remainder); for (p=j-head;p!=NULL;p=p-link) printf(%4d,p-vno+1); printf(n); 设有6种物品,它们的体积分别为:60、45、35、20、20和20单位体积,箱子的容积为100个单位体积。按上述算法的程序计算,需三只箱子,各箱子所装物品分别为:第一只箱子装物品1、3;第二只箱子装物品2、4、5;第三只箱子装物品6。 想一想上述问题的最优解是什么?贪婪法寻求的问题的解是不是原问题的最优解。习题61. 程序填空(请根据指定程序的功能,在空格处

24、将程序补充完整)从n种不同总量,不同价值的物品中选取一部分物品,要求在不超过限定重量limw的前提下,使被选取的物品的总价值最大。这里约定limw是不超过n种物品的总量的总和,也没有一种物品的总量超过limw,并且各物品的价值都大于0。 程序中,n种物品被顺序编号为0、1、2、3、.、n-1。#include#define N 3double limw;int optsN; /* 临时存储最佳选择方案,当optsi为1时,物品i在解中 */struct elem double weight; double value;aN; /* 物品重量和价值信息 */int k,n;struct int flag; /* 物品的状态:0,不选;1,考虑;2,曾被选中 */ double tw; /* 已达到的重量 */ double tv; /* 期望的总价值 */twvN; /* 当前候选解总各物品的考虑状态及候选解的状态 */void main()double maxv,find(struct elem*,int);printf(“Enter number of mater.”);scanf(“%d”,&n)printf(“Enter

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1