《信息学奥赛课课通(C++)》第9单元 基本算法.ppt

《信息学奥赛课课通(C++)》第9单元 基本算法.ppt

  1. 1、本文档共280页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
void dfs(int x,y,n1,n2; string s){ if(y = =len+1){ 输出 s; 计数器加 1, 如果等于 25000 就中止程序 ; } else if (a[i] 是元音) dfs(x+1,y+1,n1-1,n2,s+a[x]) ; else dfs(x+1,y+1,n1,n2-1,s+a[x]) ; } 直接调用 dfs(1,1,1,2, ‘ ’ )即可。但是,运行程序发现超时严重。下面考虑对递归代码(红色部分)进行适当的剪枝优化。 (1)如果接下来的字母全用上但长度也不够,则剪枝,也就是 num-xlen-(y-1)。 (2)如果接下来没有元音且之前没有用过元音,则剪枝,也就是(b[x+1]=0)且(n1=1),或者简化成 b[x+1]n1。 (3)如果接下来的辅音全取完再加上之前取的辅音也不够 2 个,则剪枝,也就是(num-x-b[x+1])+(2-n2)2,化简为 num-x-b[x+1]n2。 红色部分的递归代码优化为(具体程序见教材460页): if(a[x] 是元音 ){ if((len-y = n2) (num-x-b[x+1] = n2)) dfs(x+1,y+1,n1-1,n2,s+a[x]); }else if((len-y = n1) (b[x+1] = n1)) dfs(x+1,y+1,n1,n2-1,s+a[x]); if((num-x = len-y+1) (b[x+1] = n1) (num-x-b[x+1] = n2)) dfs(x+1,y,n1,n2,s); 实践巩固 第 11 课 回溯法 学习目标 1. 体会回溯法的基本思想。 2. 了解回溯法与深度优先搜索的关系。 3. 熟练应用回溯法求解一些实际问题。 回溯法 “回溯法”也称“试探法”。它是从问题的某一状态出发,不断“试探”着往前走一步,当一条路走到“尽头”,不能再前进(拓展出新状态)的时候,再倒回一步或者若干步,从另一种可能的状态出发,继续搜索,直到所有的“路径(状态)”都一一试探过。这种不断前进、不断回溯,寻找解的方法,称为“回溯法”。 深度优先搜索求解的时候,当找到目标结点之后,还要回头寻找初始结点到目标结点的解路径。而回溯法则不同,找到目标结点之后,搜索路径就是一条从初始结点到目标结点的解路径。回溯法实际上是状态空间搜索中,深度优先搜索的一种改进,是更实用的一种搜索求解方法。 深度优先搜索与回溯法的关系 1)深度优先搜索包含回溯,或者说回溯法是深度优先搜索的一种。 2)深度优先搜索需要控制如何实现状态之间的转移(拓展),回溯法就是深度优先搜索的一种控制策略。 3)回溯的过程中,并不需要记录整棵“搜索树”,而只需记录从初始状态到当前状态的一条搜索路径,是“线性链状”的,其最大优点是占用空间少。 4)深度优先搜索可以采用递归(系统栈)和非递归(手工栈)两种方法实现。递归搜索是系统栈实现一部分的回溯(如果需要记录一些特殊信息或较多的信息,还需要另外手工记录),而非递归是自己用手工栈模拟回溯的过程,所以实现起来略为复杂一点。 回溯法的算法框架 void search(int dep){ 自定义参数 ; if( 当前是目标状态 ){ 输出解或者作计数和评价处理 ; }else for(i = 1; i = 状态的拓展可能数 ; i++) if( 第 i 种状态拓展可行 ){ 保存现场 ( 断点 ), 维护自定义参数 ; search(dep+1); 恢复现场 , 回溯到上一个断点继续执行 ; } } 回溯法的另一种形式: void search(dep:integer){ 自定义参数 ; for(i = 1;i = 状态的拓展可能数 ;i++) if( 第 i 种状态拓展可行 ){ 保存现场 ( 断点 ), 维护自定义参数 ; if( 当前是目标状态 ){ 输出解或者作计数和评价处理 ; }else search(dep+1); 恢复现场 , 回溯到上一个断点继续执行 ; } } 例1、数的拆分 【问题描述】 输入 n,输出将 n 拆分成若干正整数和的所有方案,即 n=S 1 +S 2 +…+S k 的形式,且 S 1 ≤S 2 ≤…≤S k ,n≤20,请按照字典序输出。 【输入格式】 一行一个整数 n。 【输出格式】 所有拆分方案,具体格式参见输出样例。 【输入样例】 4 【输出样例】 1+1+1+1 1+1+2 1+3 2+2 4 total=5 【问题分析】 与深度优先搜索的方法类似,从 dep=1 开始,每次 dfs(dep)先拆出一个数 i

文档评论(0)

一壶清茶 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档