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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

算法分析防灾 leo.docx

1、算法分析防灾 leo1、P类问题:存在多项式时间(4分)算法的一类问题(1分)称作P类问题;NP问题:可以在多项式时间内验证一个解是否正确的问题2、链式存储和连续存储的优缺点分析:连续存储方式,如数组,通过下标可以直接访问数据,缺点是插入和删除操作比较麻烦;链表存储方式把逻辑上相邻的节点存储在物理上可能不相邻的单元,优点是可以充分利用所有存储空间,不会出现碎片现象,缺点是不能随机存储和访问数据。3 蛮力法蛮力法是基于计算机运算速度快这一特性,在解决问题时采取的一种“懒惰”的策略。这种策略不经过(或者说是经过很少的)思考,把问题的所有情况或所有过程交给计算机去一一尝试,从中找出问题的解。蛮力策略

2、的应用很广,具体表现形式各异,数据结构课程中学习的:选择排序、冒泡排序、插入排序、顺序查找、朴素的字符串匹配等,都是蛮力策略具体应用。比较常用还有枚举法、盲目搜索算法等4 分治算法框架1)分治法思想:将一个难以直接解决的大问题,分割成一些规模较小的几个相似问题,便于各个击破,分而治之;2)适合用分治法策略的问题(应用)当求解一个输入规模为n且取值又相当大的问题时,用蛮力策略效率一般得不到保证。若问题能满足以下几个条件,就能用分治法来提高解决问题的效率。1) 能将这n个数据分解成k个不同子集合,且得到k个子集合是可以独立求解的子问题,其中1kn;2) 分解所得到的子问题与原问题具有相似的结构,便

3、于利用递归或循环机制;在求出这些子问题的解之后,就可以推解出原问题的解; 3)算法框架分治法的一般的算法设计模式如下:Divide-and-Conquer(int n) /n为问题规模/ if (nn0) /n0 为可解子问题的规模/ 解子问题; return(子问题的解);for (i=1 ;i=k;i+) /分解为较小子问题p1,p2,pk/ yi=Divide-and-Conquer(|Pi|); /递归解决Pi/ T =MERGE(y1,y2,.,yk); /合并子问题/ return(T); 5 贪婪算法贪婪法又叫登山法, 它的根本思想是逐步到达山顶,即逐步获得最优解。贪婪算法没有固

4、定的算法框架,算法设计的关键是贪婪策略的选择。一定要注意,选择的贪婪策略要具有无后向性。某状态以后的过程不会影响以前的状态,只与当前状态或以前的状态有关,称这种特性为无后效性。因此,采用贪婪算法的问题较少。如Hoffman树、构造最小生成树的Prim算法、Kruskal算法等,都属于贪婪算法。6 动态规划1 )动态规划的基本思想动态规划方法的基本思想是,把求解的问题分成许多阶段或多个子问题,然后按顺序求解各子问题。最后一个子问题就是初始问题的解2)适合动态规划的问题特征动态规划算法的问题及决策应该具有三个性质:最优化原理、无后向性、子问题重叠性质3) 标准动态规划的基本框架for( j=1 ;

5、j=1;i=i-1) /其它n-1个阶段 for (j=1 ;j=f(i) ;j=j+1)/ f(i)与 i有关的表达式 xij=j=max(或min)g(xi-1j1j2),g(xi-1jkjk+1);t=g(x1j1j2); /由最优解求解最优解的方案print(x1j1);for( i=2 ;i=f(i) ;j=j+1) if(t= xiji) break;7 回溯法1)回溯法基本思想 回溯法是在包含问题的所有解的解空间树中。按照深度优先的策略,从根结点出发搜索解空间树,算法搜索至解空间树的任一结点时,总是先判断该结点是否满足问题的约束条件。如果满足进入该子树,继续按深度优先的策略进行搜

6、索。否则,不去搜索以该结点为根的子树,而是逐层向其祖先结点回溯。 回溯法就是对隐式图的深度2)算法框架 1)问题框架 设问题的解是一个n维向量(a1,a2,an),约束条件是ai(i=1,2,3n)之间满足某种条件,记为f(ai)2)非递归回溯框架int an,i;初始化数组a ;i=1;While (i0(有路可走) and (未达到目标) /还未回溯到头 if (in) /正在处理第i个元素 搜索到一个解,输出; else ai第一个可能的值; while (ai在不满足约束条件 且 在搜索空间内) ai下一个可能的值; if (ai在搜索空间内) 标识占用的资源; i=i+1; /扩展下

7、一个结点 else 清理所占的状态空间; i=i-1;/回溯 3)递归算法框架 一般情况下用递归函数来实现回溯法比较简单,其中i为搜索深度。int an;try(int i)if(in) 输出结果; else for( j=下界 ; j=上界; j+) /枚举i所有可能的路径 if( f(j) ) /满足限界函数和约束条件 ai=j; /其它操作 try(i+ 1); 回溯前的清理工作(如ai置空值等); 3)应用排列及排列树的回溯搜索; 最优化问题的回溯搜索8 分支限界法1)基本思想分支搜索法也是一种在问题解空间上进行尝试搜索算法。所谓“分支”是采用广度优先的策略,依次生成E-结点所有分支,

8、也就是所有的儿子结点。“限界”是加速搜索速度而采用的启发信息剪枝的策略。和回溯法一样,在生成的节点中,抛弃那些不满足约束条件(或者说不可能导出最优可行解)的结点,其余节点加入活节点表。然后从表中选择一个节点作为下一个E-节点。2)算法框架如下:search(T) /为找出最小成本答案结点检索T。 leaf=0; 初始化队;ADDQ(T); /根结点入队 parent(E)=0; /记录扩展路径,当前结点的父结点 while (队不空)DELETEQ(E) /队首结点出队为新的E结点; for (E的每个儿子 X) if (s(X)u) /当是可能的最优解时入队 ADD Q(X); parent

9、(X)=E; if (X是解结点 ) /x为叶结点 U=min(cost(X),u); leaf=x; /方案的叶结点存储在leaf中 print(”least cost=,u);while (leaf0) /输出最优解方案 print(leaf); leaf=parent(leaf);9、广度优先搜索1)算法的基本思路算法设计的基本步骤为:1)确定图的存储方式; 2)图的遍历过程中的操作,其中包括为输出问题解而进行的存储操作; 3)输出问题的结论。2)算法框架从广度优先搜索定义可以看出活结点的扩展是按先来先处理的原则进行的,所以在算法中要用“队”来存储每个E-结点扩展出的活结点。为了算法的简

10、洁,抽象地定义:queue为队列类型,InitQueue( ) 为队列初始化函数, EnQueue(Q,k)为入队函数,QueueEmpty(Q) 为判断队空函数,DeQueue(Q) 为出队函数。 实际应用中,用数组或链表实现队列。 开辟数组visited记录visited结点的搜索情况。 在算法框架中以输出结点值表示“访问”。A、邻接表表示图的广度优先搜索算法int visitedn; /n 为结点个数/bfs(int k,graph head) int i;queue Q ; edgenode *p; /定义队列/ InitQueue(Q); /队列初始化/ print(“visit v

11、ertex”,k); / 访问源点vk/ visitedk=1; EnQueue(Q,k); /vk已访问,将其入队。/ while(!QueueEmpty(Q) /队非空则执行/ i=DeQueue(Q); / vi出队为E-结点/ p=headi.firstedge; /取vi的边表头指针/ while(pnull) /扩展E-结点 / if(visitedp-adjvex=0) /若vj未访问过/ print (“visitvertex”,p-adjvex);/访问vj/ visitedp-adjvex=1; EnQueue(Q,p-adjvex); /访问过的vj人队/ p=p-nex

12、t; /找vi的下一邻接点/ B、邻接矩阵表示的图的广度优先搜索算法bfsm(int k, graph g100,int n) int i,j; queue Q; InitQueue(Q); print (“visit vertex”, k); /访问源点vk/ visitedk=1; EnQueue(Q,k); while(not QueueEmpty(Q) i=DeQueue(Q); /vi出队/ for(j=0;jn;j+) /扩展结点/if(gij=1 and visitedj=0) print(“visit vertex”,j); visitedj=1; EnQueue(Q,j);

13、/访问过的vj入队/ 10、深度优先搜索深度优先遍历首先访问出发点v,并将其标记为已访问过;然后依次从v出发搜索v的每个邻接点w。若w未曾访问过,则以w为新的出发点继续进行深度优先遍历,直至图中所有和源点v有路径相通的顶点均已被访问为止。 若此时图中仍有未访问的顶点,则另选一个尚未访问的顶点作为新的源点重复上述过程,直至图中所有顶点均已被访问为止。1)算法的基本思路算法设计的基本步骤为: 1)确定图的存储方式; 2)遍历过程中的操作,其中包括为输出问题解而进行的存储操作; 3)输出问题的结论。 4)一般在回溯前的应该将结点状态恢复为原始状态,特别是在有多解需求的问题中。A、 用邻接表存储图的搜

14、索算法int visitedn; /n为节点个数,数组初始值为0graph head100;dfs(int k) / head图的顶点数组/ edgenode *ptr / ptr图的边表指针/ visitedk=1; /* 记录已遍历过 */ print(“访问 ”,k); /* 遍历顶点值 */ ptr=headk.firstedge; /* 顶点的第一个邻接点 */ while ( ptr NULL ) /* 遍历至链表尾 */ if( visitedptr-vertex=0) /* 如过没遍历过 */ dfs(ptr-vertex); /* 递归遍历 */ ptr = ptr-next

15、node; /* 下一个顶点 */ 算法分析:n图中有n个顶点,e条边。扫描边的时间为(e)。遍历图的时间复杂性为(n+e)。B、 用邻接矩阵存储图的搜索算法int visitedn;graph g100100,int n;dfsm(graph g,int k) int j; print(“访问 ”,k); visitedk=1; for(j=1;j1时,(a+b)n的中间各项系数是(a+b)n-1的相应两项系数之和,如果把(a+b)n的n+1的系数列为数组c,则除了c(1)、c(n+1)恒为1外,设(a+b)n的系数为c(i),(a+b)n-1 的系数设为c (i)。则有:c(i)=c(i)

16、+c(i-1)而当n=1时,只有两个系数 c(1) 和 c(2) (值都为1)。不难看出,对任何n, (a+b)n的二项式系数可由(a+b)n-1的系数求得,直到n=1时,两个系数有确定值,故可写成递归子算法。复杂度:O(n2)coeff(int a ,int n) if (n=1) a1=1; a2=1; else coeff(a,n-1); an+1=1; for (i=n;i=2;i- -) ai=ai+ai-1; a1=1; main( )int a100,i,n; input( n ); for(i=1;i=n;i=i+1) input(ai); coeff(a,n); for(i=

17、1;i2算法设计:算法可以用递归或循环完成。下面是问题的递归算法。算法如下:main( ) int n:; print(n=); input(n); print(f(,n,)=,f(n);f(int n) if (n = 1 ) return(1); if (n = 2 ) return(2); else return(f(x-1)+f(x-2);【例1】兔子繁殖问题问题描述:一对兔子从出生后第三个月开始,每月生一对小兔子。小兔子到第三个月又开始生下一代小兔子。假若兔子只生不死,一月份抱来一对刚出生的小兔子,问一年中每个月各有多少只兔子。问题分析:因一对兔子从出生后第三个月开始每月生一对小兔子

18、,则每月新下小兔子的对儿数(用斜体数字表示)显然由前两个月的小兔子的对儿数决定。则繁殖过程如下: 一月 二月 三月 四月 五月 六月 1 1 1+1=2 2+1=3 3+2=5 5+3=8 数学建模:y1=y2=1,yn=yn-1+yn-2,n=3,4,5,。算法2:表4-1 递推迭代表达式1 2 3 4 5 6 7 8 9a b c=a+b a=b+c b=a+c c=a+b a=b+c b=a+c 由此归纳出可以用“c=a+b; a=b+c; b=c+a;”做循环“不变式”。算法2如下: main( ) int i,a=1,b=1; print(a,b); for(i=1; i=4;i+)

19、 c=a+b; a=b+c; b=c+a; print(a,b,c); 【例5】穿越沙漠问题 用一辆吉普车穿越1000公里的沙漠。吉普车的总装油量为500加仑,耗油率为1加仑/公里。由于沙漠中没有油库,必须先用这辆车在沙漠中建立临时油库。该吉普车以最少的耗油量穿越沙漠,应在什么地方建油库,以及各处的贮油量。 数学模型:根据耗油量最少目标的分析,下面从后向前分段讨论。第一段长度为500公里且第一个加油点贮油为500加仑。第二段中为了贮备油,吉普车在这段的行程必须有往返。下面讨论怎样走效率高:1)首先不计方向这段应走奇数次(保证最后向前走)。2)每次向前行进时吉普车是满载。3)要能贮存够下一加油点

20、的贮油量,路上耗油又最少。下图是满足以上条件的最佳方案,此段共走3次:第一、二次来回耗油2/3贮油1/3,第三次耗油1/3贮油2/3,所以第二个加油点贮油为1000加仑。由于每公里耗油率为1加仑,则此段长度为500/3公里。第三段与第二段思路相同。下图是一最佳方案此段共走5次:第一、二次来回耗油2/5贮油3/5,第三、四次来回耗油2/5贮油3/5,第五次耗油1/5贮油4/5,第三个加油点贮油为1500加仑。此段长度为500/5。 500/5公里 第二 第三 终点贮油点(500)贮油点(1000)贮油点(1500)图4-4 贮油点及贮油量示意综上分析,从终点开始分别间隔 500,500/3,50

21、0/5,500/7,(公里)设立贮油点,直到总距离超过1000公里。每个贮油点的油量为500,1000,1500,。 算法设计:由模型知道此问题并不必用倒推算法解决(只是分析过程用的是倒推法),只需通过累加算法就能解决。变量说明:dis表示距终点的距离,1000- dis则表示距起点的距离,k表示贮油点从后到前的序号。desert( ) int dis,k,oil,k; dis=500;k=1;oil=500; do print(“storepoint”,k,”distance”,1000-dis,”oilquantity”,oil); k=k+1; dis=dis+500/(2*k-1);

22、oil= 500*k; while ( dis1000) oil=500*(k-1)+(1000-dis)*( 2*k-1); print(“storepoint”,k,”distance”,0,”oilquantity”,oil); 走迷宫问题方法一:广度优先搜索算法:算法设计:从入口开始广度优先搜索可到达的方格入队,再扩展 队首的方格,直到搜索到出口时算法结束。 对于迷宫中任意一点A(Y,X),有四个搜索方向: 向上A(Y-1,X) 向下A(Y+1,X) 向左A(Y,X-1) 向右A(Y,X+1) 当对应方格可行(值为0),就扩展为活结点。数据结构设计:用数组做队的存储空间,队中结点有三个

23、成员:行号、列号、前一个方格在队列中的下标。搜索过的方格不另外开辟空间记录其访问的情况,而是用迷宫原有的存储空间置元素值为“-1”时,标识已经访问过该方格。 为了构造循环体,用数组fx=1,-1,0,0、fy= 0,0,-1,1 模拟上下左右搜索时的下标的变化过程。 int maze88=0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0, 0,1,1,1,1,1,1,0;struct int x,y,pre; sq100;

24、int qh,qe,i,j,k;main( )search( ); search( )qh=0; qe=1;sq1.pre=0; sq1.x=1; sq1.y=1; maze11=-1;while( qhqe) /当队不空/qh=qh+1; /结点出队/ for(k=1;k=4;k+) /扩展结点/ i=sqqh.x+fxk; j=sqqh.y+fyk; if(check(i,j)=1) qe=qe+1; /结点入队/ sqqe.x=i;sqqe.y=j; sqqe.pre=qh; mazeij=-1;if(sqqe.x=8 and sqqe.y=8) out( ); return; prin

25、t(“No Available Way.”); check(int i, int j ) int flag=1; if(i8 or j8) /是否在迷宫 flag=0; if(mazeij=1 or mazeij=-1) /是否可行flag=0; return flag; out( ) /输出路径 print(“(“,sqqe.x,”,”,sqqe.y,”)”);while(sqqe.pre0) qe=sqqe.pre; print(-,”(“,sqqe.x,”,”,sqqe.y,”)”); 算法分析: 算法的时间复杂度并不复杂是O(n),算法的空间复杂性为O(n2),包括图本身的存储空间和搜

26、索时辅助空间“队”的存储空间。 走迷宫问题方法二:深度优先搜索算法:算法设计:深度优先搜索,就是一直向着可通行的下一个方格行进,直到搜索到出口就找到一个解。若行不通时,则返回上一个方格,继续搜索其它方向。数据结构设计:我们还是用迷宫本身的存储空间,除了记录走过的信息,还要标识是否可行: mazeij=3 标识走过的方格 mazeij=2 标识走入死胡同的方格这样,最后存储为“3”的方格为可行的方格。而当一个方格四个方向都搜索完还没有走到出口,说明该方格或无路可走或只能走入了“死胡同”。算法如下:int maze88=0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,0,0,1,0,1,0, 0,1,0,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,1,1,1,1,1,0,fx4=1,-1,0,0, fy4=0,0,-1,1,i,j,k,total;main( ) int total=0; maze

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

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