今天, AC 你 了吗? 2019/4/26.

Slides:



Advertisements
Similar presentations
1 第 3 章 C++ 中的条件与循环 第 3 次见面! acm.nefu.edu.cn/C++_03.ppt.
Advertisements

首页 全国高等学校招生考试统一考试 监考员培训 广州市招生考试委员会办公室.
延边大学 2016年度本科专业评估指标体系解读.
人口增长.
第一章 会计法律制度 补充要点.
二、个性教育.
2011年10月31日是一个令人警醒的日子,世界在10月31日迎来第70亿人口。当日凌晨,成为象征性的全球第70亿名成员之一的婴儿在菲律宾降生。 ?
什么是工业? 采取自然物质资源,制造生产资料 、生活资料,或对农产品、半成品进行加工的生产事业。
江苏省2008年普通高校 招生录取办法 常熟理工学院学生处
“八皇后”问题 崔萌萌 吕金华.
新准则框架与首次执行 企业会计准则 主讲人:陈清宇.
初级会计实务 第八章 产品成本核算 主讲人:杨菠.
碘缺乏病.
问题解决与创造思维 刘 国 权 吉林省高等学校师资培训中心.
中考阅读 复习备考交流 西安铁一中分校 向连吾.
第四单元 自觉依法律己 避免违法犯罪.
请将手机调整到静音状态 实验网站:program3.ccshu.net 资源网站:class.ccshu.org/ /
财经法规与会计职业道德 (3) 四川财经职业学院.
中央广播电视大学开放教育 成本会计(补修)期末复习
人教版义务教育课程标准实验教科书 小学数学四年级上册第七单元《数学广角》 合理安排时间 248.
安全系着你我他 安全教育知识竞赛.
補充: Input from a text file
第13章 游戏中的人工智能.
面向海洋的开放地区——珠江三角洲 山东省高青县实验中学:郑宝田.
“08高考化学学业水平(必修科目)测试的命题和教学对策研究”
第四课时 常见天气系统 阜宁一中 姚亚林.
中考语文积累 永宁县教研室 步正军 2015.9.
小学数学知识讲座 应用题.
勾股定理 说课人:钱丹.
欢迎来到我们的课堂!.
倒装句之其他句式.
必备职业素养 主讲:程华.
江苏省2009年普通高校 招生录取办法 江苏省教育考试院
第四章第一节 增值税法律制度2 主讲老师:梁天 经济法基础.
第 22 课 孙中山的民主追求 1 .近代变法救国主张的失败教训: “师夷之长技以制 夷”“中体西用”、兴办洋务、变法维新等的失败,使孙中山
高级语言程序设计 主讲人:陈玉华.
Class 2 流程控制-選擇敘述與迴圈.
程序设计II 第三讲 字符串处理.
程序讲解 第一题: 将指定文件的m行到n行字符写到显示屏上,m和n值从键盘输入。 运行时输入及结果: please enter m,n:
QQ: 李祥 QQ: 欢迎多种方式的学习交流,祝大家学有所成.
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
人教版数学四年级(下) 乘法分配律 单击页面即可演示.
計數式重複敘述 for 迴圈 P
东北林业大学 陈宇 ACM程序设计 东北林业大学 陈宇
4.8 平行线 海南华侨中学 王应寿.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第4讲 C++程序控制结构(二) 4.1 循环结构 4.2 转向控制 4.3 综合案例分析.
11308: Bankrupt Baker ★★☆☆☆ 題組:Problem Set Archive with Online Judge
知识点二 国际环境法的实施.
第五节 并查集.
今天, AC 你 了吗? 2019/4/21.
C语言程序设计 李祥 QQ:
資料結構與C++程式設計進階 遞迴(Recursion) 講師:林業峻 CSIE, NTU 6/ 17, 2010.
二分查找的应用 ——李江贝, 郝琰 2017年9月28日.
第二章 类型、对象、运算符和表达式.
第八节 算术运算符和算术表达式.
ACM 程序设计 计算机学院 刘春英 2019/5/23.
第五章 逻辑运算和判断选取控制 §5.1 关系运算符和关系表达式
第七章  数 组.
1753: Need for Speed ★★☆☆☆ 題組:Problem Set Archive with Online Judge
第十二章 位运算.
坚持,努力,机会留给有准备的人 第一章 四大金融资产总结 主讲老师:陈嫣.
美丽的旋转.
Introduction to the C Programming Language
10107: What is the Median? ★★☆☆☆
畢氏定理(百牛大祭)的故事 張美玲 製作 資料來源:探索數學的故事(凡異出版社).
12439: February 29 ★☆☆☆☆ 題組:Problem Set Archive with Online Judge
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
隨機函數.
102年人事預算編列說明 邁向頂尖大學辦公室製作.
Presentation transcript:

今天, AC 你 了吗? 2019/4/26

第八讲 一招制敌之搜索题 2019/4/26

统计信息: 根据“信息学初学者之家”网站的统计,Ural(俄罗斯的Ural州立大学的简称 ,那里设立了一个Ural Online Problem Set,并且支持Online Judge。 )的题目类型大概呈如下的分布: 搜索 动态规划 贪心 构造 图论 约10% 约15% 约5% 约5% 约10% 计算几何 纯数学问题 数据结构 其它 约5% 约20% 约5% 约25% 2019/4/26

搜索题特点分析: 题意容易理解 算法相对固定 编程有路可循 竞赛必备知识 2019/4/26

引言 “算法中最基本和常用的是搜索,主要是回溯和分支限界法的使用。这里要说的是,有些初学者在学习这些搜索基本算法是不太注意剪枝,这是十分不可取的,因为所有搜索的题目给你的测试用例都不会有很大的规模,你往往察觉不出程序运行的时间问题,但是真正的测试数据一定能过滤出那些没有剪枝的算法。实际上参赛选手基本上都会使用常用的搜索算法,题目的区分度往往就是建立在诸如剪枝之类的优化上了。 ” ——摘自《ACM竞赛之新人向导 》 2019/4/26

什么是搜索算法呢? 搜索过程实际上是根据初始条件和扩展规则构造一棵解答树并寻找符合目标状态的节点的过程。 搜索算法是利用计算机的高性能来有目的地穷举一个问题的部分或所有的可能情况,从而求出问题的解的一种方法。 搜索过程实际上是根据初始条件和扩展规则构造一棵解答树并寻找符合目标状态的节点的过程。 2019/4/26

预热一下:二分查找 2 3 4 5 6 8 12 20 32 45 65 74 86 95 100 tail head mid 2 3 4 5 6 8 12 20 32 45 65 74 86 95 100 tail head mid 2019/4/26

查找示意图: …… A[1]~A[15] A[1]~A[7] A[9]~A[15] A[1]~A[3] A[5]~A[7] 2019/4/26

思考: 1、在一百万个元素里查找某个元素大约需要比较多少次? 2、时间复杂度:O(logN) 2019/4/26

举例分析 从简单的字符串搜索讲起 2019/4/26

HDOJ_1238 Substrings 题目链接 Sample Output 2 2 Sample Input 2 3 ABCD BCDFF BRCD 2 rose orchid Sample Output 2 2 2019/4/26

题目分析: 这是一道入门级别的搜索题,基本思想比较简单,但是如果用最朴素的算法,可能会超时如何降低算法的复杂度呢? 下面的算法如何: 先将字符串按长度从短到长排序,枚举最短的字符串的子串,判断是否都是别的字符串的子串,求出最大长度即可。 2019/4/26

说明: 强烈推荐!! 本题除了可以练习基本搜索算法,也是练习字符串处理的好题目,题中用到的相关知识点有: 求反串 求子串 字符串查找 求字符串长度 强烈推荐!! 2019/4/26

再来一道数值型搜索题 2019/4/26

HDOJ_1239 Calling Extraterrestrial Intelligence Again 题目链接 Sample Input 5 1 2 99999 999 999 1680 5 16 1970 1 1 2002 4 11 0 0 0 Sample Output 2 2 313 313 23 73 43 43 37 53 2019/4/26

获取有用信息 p*q<=m; a/b <= p/q <= 1; a.给定整数m,a,b(4 < m <= 100000 and 1 <= a <= b <= 1000) b.需要找到两个数(不妨设为p,q)满足以下条件: p,q均为质数; p*q<=m; a/b <= p/q <= 1; c.输出所有满足以上条件的p,q中乘积最大的一对p,q 2019/4/26

算法分析 从所有可能的p,q中寻找满足条件的一对 2.p,q的要求 p,q均为质数,且p<=q<=100000; 1.典型的搜索 从所有可能的p,q中寻找满足条件的一对 2.p,q的要求 p,q均为质数,且p<=q<=100000; 3.按上述思想流程应为 a.从1—100000中搜出质数 b.两层循环,试遍所有的组合(p,q可能相等) c.每种组合去判断是否符合条件,如是,将p*q与当前最大值比较,判断,保存 2019/4/26

面临的问题: 超时! 从1—100000的质数运算约为1e+8,而这只是准备工作。 因此,如不加以分析简化此题无法在规定时间内出解 2019/4/26

深入分析 p,q的范围其实可在2—50000(why?) 然而,这是最小的范围吗? 考虑大于10000的某个质数,不妨设为Q,另一个质数为P,则: 如果P<10,P/Q<0.001 如果P>10,P*Q>100000 而考虑到a,b的取值范围(1<=a<=b<=1000) 可知min(a/b)=0.001 同时,要求: p*q<=m<=100000 所以无论如何质数都不能超过10000。(事实上,不会超过9091) 2019/4/26

搜索时的技巧: 搜索顺序很重要。建议从大往小搜 ( num:质数的个数 ) for (i=num-1;i>=0;i--) for (j=i;j<=num-1;j++) …… 注意剪枝: If ( a[j]>m || a[j]*a[i]>m || ( (double)a[i]/a[j])<s ) …… 2019/4/26

真正的搜索题 迷宫搜索 2019/4/26

预备知识——树的遍历 分别有什么特点呢? 树的遍历主要有如下四种方法: 1.先根/序遍历 2.中根/序遍历 3.后根/序遍历 4.层次遍历 2019/4/26

(1)先根遍历 对树的访问次序是: 示例如下: 1.先访问根结点 2.再访问左子树 3.最后访问右子树 4.对于左右子树的访问也要满足以上规则 示例如下: 2019/4/26

2 1 3 5 7 4 6 以上二叉树的先根遍历序列是:?? 1、2、4、5、3、6、7 2019/4/26

(2)中根遍历 对树的访问次序是: 示例如下: 1.先访问左子树 2.再访问根结点 3.最后访问右子树 4.对于左右子树的访问也要满足以上规则 示例如下: 2019/4/26

2 1 3 5 7 4 6 以上二叉树的中根遍历序列是:?? 4、 2、 5、 1、 6、 3、 7 2019/4/26

(3)后根遍历 对树的访问次序是: 示例如下: 1.先访问左子树 2.再访问右子树 3.最后访问根结点 4.对于左右子树的访问也要满足以上规则 示例如下: 2019/4/26

2 1 3 5 7 4 6 以上二叉树的后根遍历序列是:?? 4、5、 2、 6、7 、 3、 1 2019/4/26

(4)层次遍历 对树的访问次序是: 示例如下: 1.先访问根结点 2.再访问根结点的子节点(即第二层节点) 3.再访问第三层节点 4. …… 2019/4/26

2 1 3 5 7 4 6 以上二叉树的层次遍历序列是:?? 1、2、 3、 4、5、6、7 2019/4/26

几个基本概念: 初始状态:略 目标状态:略 状态空间:由于求解问题的过程中分枝有很多(主要是求解过程中求解条件的不确定性、不完备性造成的),使得求解的路径很多,这就构成了一个图,我们说这个图就是状态空间。 状态空间搜索:就是将问题求解过程表现为从初始状态到目标状态寻找这个路径的过程。通俗点说,就是在解一个问题时,找到一条解题的过程,可以从求解的开始到问题的结果。 2019/4/26

例 九宫重排问题 2 8 3 1 6 4 7 5 1 2 3 8 4 7 6 5 初始状态: 目标状态: 2019/4/26

2 8 3 1 6 4 7 5 2 8 3 1 6 4 7 5 2 8 3 1 4 7 6 5 2 8 3 1 6 4 7 5 2 3 1 8 4 7 6 5 2 8 3 1 4 7 6 5 2 8 3 1 4 7 6 5 8 3 2 1 4 7 6 5 2 8 3 7 1 4 6 5 2 3 1 8 4 7 6 5 2 3 1 8 4 7 6 5 2019/4/26

2 3 1 8 4 7 6 5 1 2 3 8 4 7 6 5 1 2 3 8 4 7 6 5 1 2 3 7 8 4 6 5 2019/4/26

三、广度优先搜索 基本思想:从初始状态S开始,利用规则,生成所有可能的状态。构成树的下一层节点,检查是否出现目标状态G,若未出现,就对该层所有状态节点,分别顺序利用规则。生成再下一层的所有状态节点,对这一层的所有状态节点检查是否出现G,若未出现,继续按上面思想生成再下一层的所有状态节点,这样一层一层往下展开。直到出现目标状态为止。 2019/4/26

BFS算法: (1)把起始节点S线放到OPEN表中 (2)如果OPEN是空表,则失败退出,否则继续。 (3)在OPEN表中取最前面的节点node移到CLOSED 表中。 (4)扩展node节点。若没有后继(即叶节点),则转向(2)循环。 (5)把node的所有后继节点放在OPEN表的末端。各后继结点指针指向node节点。 (6)若后继节点中某一个是目标节点,则找到一个解,成功退出。否则转向(2)循环。 2019/4/26

搜索过程如下: S L O P Q R T U V W A B C D E F G 广度优先搜索示意图 2019/4/26

广度优先搜索过程中的OPEN表和CLOSED表 例1、示意图节点的搜索 OPEN CLOSED S L,O,P Q,R,T U,V,W A,B,C S L O P Q R 广度优先搜索过程中的OPEN表和CLOSED表 2019/4/26

四、深度优先搜索 基本思想:从初始状态S开始,利用规则生成搜索树下一层任一个结点,检查是否出现目标状态G,若未出现,以此状态利用规则生成再下一层任一个结点,再检查是否为目标节点G,若未出现,继续以上操作过程,一直进行到叶节点(即不能再生成新状态节点),当它仍不是目标状态G时,回溯到上一层结果,取另一可能扩展搜索的分支。生成新状态节点。若仍不是目标状态,就按该分支一直扩展到叶节点,若仍不是目标,采用相同的回溯办法回退到上层节点,扩展可能的分支生成新状态,…,一直进行下去,直到找到目标状态G为止。 2019/4/26

搜索过程如下: S A H B F L I C D G J K E 深度优先搜索示意图 2019/4/26

DFS算法 (1)把起始节点S线放到OPEN表中。 (2)如果OPEN是空表,则失败退出,否则继续。 (3)从OPEN表中取最前面的节点node移到CLOSED 表中。 (4)若node节点是叶结点(若没有后继节点),则转向(2)。 (5)扩展node的后继节点,产生全部后继节点,并把他们放在OPEN表的前面。各后继结点指针指向node节点。 (6)若后继节点中某一个是目标节点,则找到一个解,成功退出。否则转向(2)循环。 2019/4/26

例、节点搜索示意图 OPEN CLOSED S A, H, R, F, C, D E S A B C D E 2019/4/26

小结: 广度和深度优先搜索有一个很大的缺陷,就是他们都是在一个给定的状态空间中穷举。这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不预测的情况下就不可取了。他的效率实在太低,甚至不可完成。 所以,在这里再次强调“剪枝”! 2019/4/26

HDOJ_1010 Tempter of the Bone Sample Input 4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0 Sample Output NO YES 2019/4/26

要点分析: 典型的迷宫搜索,做出该题将具有里程碑式的意义! 每个block只能走一次 要求恰好某个给定的时间到达出口 2019/4/26

想到了什么剪枝条件? 如果可走的block的总数小于时间,将会产生什么情况? 还想到什么剪枝? 2019/4/26

奇偶性剪枝 结论: 所以当遇到从 0 走向 0 但是要求时间是奇数的,或者, 从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可达! 可以把map看成这样: 0 1 0 1 0 1 1 0 1 0 1 0 从为 0 的格子走一步,必然走向为 1 的格子 从为 1 的格子走一步,必然走向为 0 的格子 即: 0 ->1或1->0 必然是奇数步 0->0 走1->1 必然是偶数步 结论: 所以当遇到从 0 走向 0 但是要求时间是奇数的,或者, 从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可达! 2019/4/26

这个题目没问题了吧? 2019/4/26

思考: 求某给定时间以内能否找到出口 找到出口的最短时间 条件变为可以停留 2019/4/26

附录:推荐搜索题: 1010、1240、1241、1242 1072、 1253 、 1312、1372 (以上题目类似于1010) 1238、1239、1015、1016 1401、1515、1548 2019/4/26

课后一定要练习! 2019/4/26

ACM, 天天见! 2019/4/26

while(cin>>n>>m>>t) if(n==0&&m==0&&t==0) break; int main() { int i,j,si,sj; while(cin>>n>>m>>t) if(n==0&&m==0&&t==0) break; int wall=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>map[i][j]; if(map[i][j]=='S') { si=i; sj=j; } else if(map[i][j]=='D') { di=i; dj=j; } else if(map[i][j]=='X') wall++; } if(n*m-wall<=t) cout<<"NO"<<endl; continue; escape=0; map[si][sj]='X'; dfs(si,sj,0); if(escape) cout<<"YES"<<endl; else cout<<"NO"<<endl; return 0; 附录:hdoj_1010月下版 # include <iostream.h> # include <string.h> # include <stdlib.h> char map[9][9]; int n,m,t,di,dj; bool escape; int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; void dfs(int si,int sj,int cnt) { int i,temp; if(si>n||sj>m||si<=0||sj<=0) return; if(cnt==t&&si==di&&sj==dj) escape=1; if(escape) return; temp=(t-cnt)-abs(si-di)-abs(sj-dj); if(temp<0||temp&1) return; for(i=0;i<4;i++){ if(map[si+dir[i][0]][sj+dir[i][1]]!='X') { map[si+dir[i][0]][sj+dir[i][1]]='X'; dfs(si+dir[i][0],sj+dir[i][1],cnt+1); map[si+dir[i][0]][sj+dir[i][1]]='.'; } return; 2019/4/26