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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

算法八大类算法原理与例子.docx

1、算法 八大类算法原理与例子目录算法设计与基础 1目录 2一、蛮力法 3原理 3例子 平面最近的点对 3二、动态规划 5原理 5例子:最长公共子序列 6三、分治算法 9原理 9例子 棋盘覆盖 9四、贪心算法 11原理 11例子 背包问题 11五、回溯法 14原理 14例子 八皇后问题 14六、分支界限法 16原理 16例子 装载问题 16七、时空权衡 17原理 17例子 KMP字符串匹配算法 18八、变治法 25原理 25例子 堆排序 25一、蛮力法原理顾名思义,蛮力法即是顺序往下寻找方法,直到问题的解决。它所依赖的技术是扫描技术,关键是依次处理所有元素。蛮力法的思想非常简单,没有很多条件的限制

2、,比如动态划法,必须满足最有性原理才可以使用。它的方法上也没有缺陷,对于分治法,一旦子问题的规模不同,便不能在使用。而蛮力法则没有这个要求。因此,简单,易上手,是蛮力法的基本原理。蛮力法是我们算法中最常使用的算法,虽然巧妙和高效的算法很少来自于蛮力法,但是蛮力法依然是一种重要的算法设计技术。在实际理论上,蛮力法可以解决可计算领域的各种问题,只是效率的高低不同而已。因此蛮力法经常用来解决一些较小规模的问题。蛮力法对于一些重要的问题可以产生一些合理的算法,他们具备一些实用价值,而且不受问题规模的限制。蛮力法也可以作为某类问题时间性能的底限,来衡量同样问题的更高效算法。例子 平面最近的点对问题:设p

3、1=(x1, y1), p2=(x2, y2), , pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。蛮力算法描述:int ClosestPoints(int n, int x , int y ) minDist=Double.POSITIVE_INFINITY; for (i=1; i n; i+) for (j=i+1; j=n; j+) d=(xi-xj)* (xi-xj)+(yi-yj)* (yi-yj); if (d minDist) minDist=d; index1=i; index2=j; return minDist; 程序:import

4、 java.util.*;public class ClosestPair1 public static void main(String args) /* *输入需要比较的点的对数存在变量n中 */ Scanner in=new Scanner(System.in); System.out.println(How many pairs of points to compare?(有多少对点需要比较?); int n=in.nextInt(); int x=new intn; int y=new intn; /* *输入这些点的横坐标和纵坐标分别存储在xn和yn */ System.out.p

5、rintln(Please enter these points,X-coordinate(请输入这些点,横坐标):); for(int i=0;i n;i+) xi=in.nextInt(); System.out.println(Please enter these points,Y-coordinate(请输入这些点,纵坐标):); for(int i=0;i n;i+) yi=in.nextInt(); double minDist=Double.POSITIVE_INFINITY; double d; int indexI=0; int indexJ=0; /* *求解最近对距离存于

6、minDist中 */ double startTime=System.currentTimeMillis();/startTime for(int i=0;i n-1;i+) for(int j=i+1;j n;j+) d=Math.sqrt(xi-xj)*(xi-xj)+(yi-yj)*(yi-yj); if(d minDist) minDist=d; indexI=i; indexJ=j; double endTime=System.currentTimeMillis();/endTime /* *打印输出最后求出的结果,最近的是哪两个点,以及最近距离和程序用的时间 */ System.

7、out.println(The closest pair is:(+xindexI+,+yindexI+) and (+xindexJ+,+yindexJ+); System.out.println(The closest distance is +minDist); System.out.println(Basic Statements take(基本语句用时) +(endTime-startTime)+ milliseconds!); 运行:二、动态规划原理动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。

8、动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。例子:最长公共

9、子序列什么是最长公共子序列呢?举个简单的例子吧,一个数列S,若分别是两个或多个已知序列的子序列,且是所有符合条件序列中最长的,则S称为已知序列的最长公共子序列。 举例如下,如:有两个随机数列,1 2 3 4 5 6 和 3 4 5 8 9,则它们的最长公共子序列便是:3 4 5。1、序列str1和序列str2 长度分别为m和n; 创建1个二维数组Lm.n; 初始化L数组内容为0 m和n分别从0开始,m+,n+循环: - 如果str1m = str2n,则Lm,n = Lm - 1, n -1 + 1; - 如果str1m != str2n,则Lm,n = maxLm,n - 1,Lm - 1,

10、 n 最后从Lm,n中的数字一定是最大的,且这个数字就是最长公共子序列的长度 从数组L中找出一个最长的公共子序列 2、从数组L中查找一个最长的公共子序列 i和j分别从m,n开始,递减循环直到i = 0,j = 0。其中,m和n分别为两个串的长度。 如果str1i = str2j,则将stri字符插入到子序列内,i-,j-; 如果str1i != strj,则比较Li,j-1与Li-1,j,Li,j-1大,则j-,否则i-;(如果相等,则任选一个)图1 效果演示图 根据上图,我们可以得到其中公共子串:B C B A 和 B D A B。#include #include using namesp

11、ace std; int main(int argc, char *argv) string str1 = ABCBDAB; string str2 = BDCABA; int x_len = str1.length(); int y_len = str2.length(); int arr5050 = 0,0; int i = 0; int j = 0; for(i = 1; i = x_len; i+) for(j = 1; j = arri - 1j) arrij = arrij - 1; else arrij = arri -1j; for(i = 0 ; i = x_len; i+)

12、 for( j = 0; j = y_len; j+) cout arrij ; cout = 1 & j = 1;) if(str1i - 1 = str2j - 1) cout str1i - 1 = arri - 1j)/打印:B A D B if(arrij -1 arri - 1j) /打印:A B C B j-; else i-; cout endl; return 0; 三、分治算法原理基本思想当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往 往先把它分解成几个子问题,找到求出这几个

13、子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把 它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。二分法利用分治策略求解时,所需时间取决于分解后子问题的个数、子问题的规模大小等因素,而二分法,由于其划分的简单和均匀的特点,是经常采用的一种有效的方法,例如二分法检索。解题步骤分治算法解题的一般步骤:(1)分解,将要解决的问题划分成若干规模较小的同类问题;(2)求解,当子问题划分得足够小时,用较简单的方法解决;(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。例子 棋盘覆盖题目:在一个(2k

14、)*(2k)个方格组成的棋盘上,有一个特殊方格与其他方格不同,称为特殊方格,称这样的棋盘为一个特殊棋盘。现在要求对棋盘的其余部分用L型方块填满(注:L型方块由3个单元格组成。即围棋中比较忌讳的愚形三角,方向随意),且任何两个L型方块不能重叠覆盖。L型方块的形态如下:题目的解法使用分治法,即子问题和整体问题具有相同的形式。我们对棋盘做一个分割,切割一次后的棋盘如图1所示,我们可以看到棋盘被切成4个一样大小的子棋盘,特殊方块必定位于四个子棋盘中的一个。假设如图1所示,特殊方格位于右上角,我们把一个L型方块(灰色填充)放到图中位置。这样对于每个子棋盘又各有一个“特殊方块”,我们对每个子棋盘继续这样分

15、割,知道子棋盘的大小为1为止。用到的L型方块需要(4k-1)/3 个,算法的时间是O(4k),是渐进最优解法。本题目的C语言的完整代码如下(TC2.0下调试),运行时,先输入k的大小,(1=k=6),然后分别输入特殊方格所在的位置(x,y), 0=x,y=(2k-1)。#include int title=1;int board6464;void chessBoard(int tr,int tc,int dr,int dc,int size)int s,t;if(size=1) return;t=title+; s=size/2;if(drtr+s & dctc+s)chessBoard(tr

16、,tc,dr,dc,s);else boardtr+s-1tc+s-1=t;chessBoard(tr,tc,tr+s-1,tc+s-1,s);if(dr=tc+s)chessBoard(tr,tc+s,dr,dc,s);else boardtr+s-1tc+s=t;chessBoard(tr,tc+s,tr+s-1,tc+s,s); if(dr=tr+s & dc=tr+s & dc=tc+s)chessBoard(tr+s,tc+s,dr,dc,s);else boardtr+stc+s=t;chessBoard(tr+s,tc+s,tr+s,tc+s,s); void main()int

17、 dr=0,dc=0,s=1,i=0,j=0;printf(print in the size of chess:n);scanf(%d,&s);printf(print in specal point x,y:n);scanf(%d%d,&dr,&dc);if(drs & dcs) chessBoard(0,0,dr,dc,s);for(i=0;is;i+) for(j=0;js;j+) printf(%4d,boardij); printf(n); elseprintf(the wrong specal point!n);getch();四、贪心算法原理贪婪算法(Greedy algori

18、thm)是一种对某些求最优解问题的更简单、更迅速的设计技术。用贪婪法设计算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,它省去了为找最优解要穷尽所有可能而必须耗费的大量时间,它采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。贪婪算法是一种改进了的分级处理方法。其核心是根据题意选取一种量度标准。然后将这多个输入排成这种量度标准所要求的顺序,按这种顺序一

19、次输入一个量。如果这个输入和当前已构成在这种量度意义下的部分最佳解加在一起不能产生一个可行解,则不把此输入加到这部分解中。这种能够得到某种量度意义下最优解的分级处理方法称为贪婪算法。对于一个给定的问题,往往可能有好几种量度标准。初看起来,这些量度标准似乎都是可取的,但实际上,用其中的大多数量度标准作贪婪处理所得到该量度意义下的最优解并不是问题的最优解,而是次优解。因此,选择能产生问题最优解的最优量度标准是使用贪婪算法的核心。一般情况下,要选出最优量度标准并不是一件容易的事,但对某问题能选择出最优量度标准后,用贪婪算法求解则特别有效。最优解可以通过一系列局部最优的选择即贪婪选择来达到,根据当前状

20、态做出在当前看来是最好的选择,即局部最优解选择,然后再去解做出这个选择后产生的相应的子问题。每做一次贪婪选择就将所求问题简化为一个规模更小的子问题,最终可得到问题的一个整体最优解。例子 背包问题有N件物品和一个容量为V的背包。第i件物品的重量是ci,价值是wi。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。基本思路这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。用子问题定义状态:即fiv表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:fiv=maxfi-1v,fi-1v-ci+wi。可以压缩空间,fv=maxfv,

21、fv-ci+wi这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为fi-1v;如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-ci的背包中”,此时能获得的最大价值就是f i-1v-ci再加上通过放入第i件物品获得的价值wi。注意fv有意义当且仅当存在一个前i件物品的子集,其费用总和为v。所以按照这个方程递推完毕后

22、,最终的答案并不一定是fN V,而是fN0.V的最大值。如果将状态的定义中的“恰”字去掉,在转移方程中就要再加入一项fv-1,这样就可以保证fN V就是最后的答案。至于为什么这样就可以,由你自己来体会了。空间复杂以上方法的时间和空间复杂度均为O(N*V),其中时间复杂度基本已经不能再优化了,但空间复杂度却可以优化到O(N)。先考虑上面讲的基本思路如何实现,肯定是有一个主循环i=1.N,每次算出来二维数组fi0.V的所有值。那么,如果只用一个数组f 0.V,能不能保证第i次循环结束后fv中表示的就是我们定义的状态fiv呢?fiv是由fi-1v和f i-1v-ci两个子问题递推而来,能否保证在推f

23、v时(也即在第i次主循环中推fv时)能够得到fv和fv -ci的值呢?事实上,这要求在每次主循环中我们以v=V.0的顺序推fv,这样才能保证推fv时fv-ci保存的是状态fi-1v-ci的值。伪代码如下:for i=1.Nfor v=V.0fv=maxfv,fv-ci+wi;其中的fv=maxfv,fv-ci一句恰就相当于我们的转移方程fiv=maxfi-1v,fi-1v-ci,因为的fv-ci就相当于原来的fi-1v-ci。如果将v的循环顺序从上面的逆序改成顺序的话,那么则成了fiv由fiv-ci推知,与本题意不符,但它却是另一个重要的背包问题P02最简捷的解决方案,故学习只用一维数组解01

24、背包问题是十分必要的。示例程序#include stdafx.h#include using namespace std;#define MAXSIZE 1000int fMAXSIZE + 1,cMAXSIZE + 1,wMAXSIZE + 1;int _tmain(int argc,_TCHAR* argv)int N,V;cin N V;int i = 1;for (; i ci wi;for (i = 1; i = ci; -v) /ci可优化为bound,bound = max V - sum ci,.n,cifv = (fv fv - ci + wi?fv : fv - ci +

25、wi);/当i=N时,可以跳出循环单独计算FVcout fV n;system(pause);return 0;递归实现/现在设Aiv表示在剩余空间为v时选取当前物品i的最大值,Biv表示不选取当前物品i的最大值,所以总的最大值必然是max(Anv,Bnv),详细程序见如下:/BY wanda1416#include #includusing namespace std;#define MAXSIZE 1000int AMAXSIZE+1MAXSIZE+1,BMAXSIZE+1MAXSIZE+1;int cMAXSIZE+1,wMAXSIZE+1;int F(int n,int v)if(n=0) return 0;if(!Anv & v = cn)Anv = F(n-1,v-cn) +wn;if(!Bnv) Bnv = F(n-1,v);return AnvBnv?Anv:Bnv;int main(int argc,char *argv)int n,v;memset(A,0,sizeof(A);memset(B,0,sizeof(B);ifstream in(in.txt);o

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

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