深度、广度和双向搜索优化及其应用
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
输入样例 9 521521521 4 1234 0 输出样例 6 5
解题思路
初始状态:有N节木棒 最终状态:这N节木棒恰好被拼接成若干根等长
的棍子(裁前的东西称为棍子)
注意:棍子长度未知
枚举什么? 枚举所有有可能的棍子长度。 从最长的那根木棒的长度一直枚举到木棒长度 总和的一半。 对每个假设的棍子长度试试看能否拼齐所有棍 子:枚举长度是否可以整除棍子总长。
实现方法:用stack表示 每次取stack顶部的状态演化 每次演化出的状态s若不属于,则s将压入stack 的顶部
POJ1011 木棒问题
问题描述:
乔治拿来一组等长的棍子,将它们随机地裁断(截 断后的小段称为木棒),使得每一节木棒的长度都 不超过50个长度单位。然后他又想把这些木棒恢复 到为裁截前的状态,但忘记了棍子的初始长度。
将初态S0变换为另一个状态F(S0) F中各动作的执行顺序不影响F(S0) 如果F(S0)是符合要求的S*, 那么F是真解, 否则是
伪解
Байду номын сангаас
搜索复杂的、高级的枚举
搜索: 解空间的每个元素是一个动作的序列F 将初态S0变换为另一个状态F(S0) 如果F(S0)是符合要求的S*, 那么F是真解, 否则是 伪解 有一个规则, 确定在每个状态S下,分别有哪些动 作可供选择 采用递归的办法, 产生每个动作序列
请你设计一个程序,帮助乔治计算棍子的可能最小 长度。每一节木棒的长度都用大于零的整数表示
输入输出
输入数据 由多个案例组成,每个案例包括两行。第一行是一个不超过64的 整数,表示裁截之后共有多少节木棒。第二行是经过裁截后,所 得到的各节木棒的长度。在最后一个案例之后,是零。
输出要求 为每个案例,分别输出木棒的可能最小长度,每个案例占一行。
状态的处理: 有顺序的尝试备选动作, 每一次的尝试都 演化出另一个状态 已处理的状态: 全部备选动作都已经尝试
一个树结构: 状态之间的演化关系 递归的出口
为空 演化出目标状态S* 演化出的状态不属于
影响搜索效率的因素
两个状态的集合
: 未处理完的状态 : 已处理的状态
拼在当前棍子上,然后 exit Dfs(nUnusedSticks – 1, nLeft – len ); }
解题思路
搜索题,还要解决一个问题:如何剪枝 就本题而言,即尽可能快地发现一根拼好
的棍子需要被拆掉,以及尽量少做结果不 能成功的尝试。
剪枝1
每次开始拼第i根棍子的时候,必定选剩下的木棒 里最长的一根,作为该棍子的第一根木棒。
为len)拼在当前棍子上,然后 exit Dfs(nUnusedSticks – 1, nLeft – len ); }
Dfs的终止条件之一:
bool Dfs(int nUnusedSticks, int nLeft ) { if( nUnusedSticks = 0 and nLeft = 0 ) exit true; if( nLeft = 0 ) //一根刚刚拼完 nLeft := L; //开始拼新的一根 找一根长度不超过nLeft的木棒(假设长为len)
搜索
有顺序有策略地产生解空间的元素 每个解空间的元素表现为一定动作的执行轨迹 (trace of actions)
采用递归的策略产生解空间的元素,出口条件 轨迹已经达到终点:真解、或者伪解 轨迹不可能导出真解
搜索的过程
两个状态的集合 : 未处理完的状态 : 已处理的状态
搜索
深度优先搜索 广度优先搜索
枚举
划分解的存在范围 对范围内的元素进行逐一判断 例:求出A~I 分别对应的数字(1~9) 使得下
式成立 ABCD ×E
FGHI
枚举解法
枚举ABCDE的值,计算乘积,判断是否符 合要求。
搜索复杂的、高级的枚举
枚举: 解空间中的每个元素是一个动作(action)的 集合F
表示: 当前有nUnusedSticks根未用木棒, 而且当前正在拼的那根棍子比假定的棍子 长度短了nLeft, 那么在这种情况下能否全部 拼成功。
Dfs的基本递推关系:
bool Dfs(int nUnusedSticks, int nLeft) { ….. if( nLeft = 0 ) //一根刚刚拼完 nLeft := L; //开始拼新的一根 找一根长度不超过nLeft的木棒(假设长
即:就算由于以后的拼接失败,需要重新调整第i根 棍子的拚法,也不会考虑替换第i根棍子中的第一 根木棒(换了也没用)。如果在此情况下怎么都 无法成功,那么就要推翻第i-1根棍子的拚法。如 果不存在第i-1根棍子,那么就推翻本次假设的棍 子长度,尝试下一个长度
剪枝1
因为短木棒比较容易用来填补空缺。一根 长木棒,当然比总和相同的几根短木棒要 优先使用
Dfs递归搜索函数
Bool Dfs(int nUnusedSticks, int nLeft ) ;
Function dfs(nUnusedSticks:longint, nLeft:longint):longint
解题思路
在拼接过程中,要给用过的木棒做上标记, 以免重复使用
回溯:拼好前i根棍子,结果发现第i+1根拼 不成了,那么就要推翻第i根的拼法,重拼 第i根…..直至有可能推翻第1根棍子的拼法
解题思路
搜索题,首先要解决一个问题:按什么顺 序搜索?
把木棒按长度排序。每次选木棒的时候都 尽量先选长的。
判重:每次演化出一个状态s时,s是否属于 或者
剪枝:状态s的任意演化结果是否都属于
属于,则剪枝
演化出来的状态数量:的大小
深度优先搜索
两个状态的集合 : 未处理完的状态 : 已处理的状态
从中选择被演化状态的原则:离初态S0最远的状 态s S0到s的距离:从S0到达s使用的动作数量
解题思路
初始状态:有N节木棒 最终状态:这N节木棒恰好被拼接成若干根等长
的棍子(裁前的东西称为棍子)
注意:棍子长度未知
枚举什么? 枚举所有有可能的棍子长度。 从最长的那根木棒的长度一直枚举到木棒长度 总和的一半。 对每个假设的棍子长度试试看能否拼齐所有棍 子:枚举长度是否可以整除棍子总长。
实现方法:用stack表示 每次取stack顶部的状态演化 每次演化出的状态s若不属于,则s将压入stack 的顶部
POJ1011 木棒问题
问题描述:
乔治拿来一组等长的棍子,将它们随机地裁断(截 断后的小段称为木棒),使得每一节木棒的长度都 不超过50个长度单位。然后他又想把这些木棒恢复 到为裁截前的状态,但忘记了棍子的初始长度。
将初态S0变换为另一个状态F(S0) F中各动作的执行顺序不影响F(S0) 如果F(S0)是符合要求的S*, 那么F是真解, 否则是
伪解
Байду номын сангаас
搜索复杂的、高级的枚举
搜索: 解空间的每个元素是一个动作的序列F 将初态S0变换为另一个状态F(S0) 如果F(S0)是符合要求的S*, 那么F是真解, 否则是 伪解 有一个规则, 确定在每个状态S下,分别有哪些动 作可供选择 采用递归的办法, 产生每个动作序列
请你设计一个程序,帮助乔治计算棍子的可能最小 长度。每一节木棒的长度都用大于零的整数表示
输入输出
输入数据 由多个案例组成,每个案例包括两行。第一行是一个不超过64的 整数,表示裁截之后共有多少节木棒。第二行是经过裁截后,所 得到的各节木棒的长度。在最后一个案例之后,是零。
输出要求 为每个案例,分别输出木棒的可能最小长度,每个案例占一行。
状态的处理: 有顺序的尝试备选动作, 每一次的尝试都 演化出另一个状态 已处理的状态: 全部备选动作都已经尝试
一个树结构: 状态之间的演化关系 递归的出口
为空 演化出目标状态S* 演化出的状态不属于
影响搜索效率的因素
两个状态的集合
: 未处理完的状态 : 已处理的状态
拼在当前棍子上,然后 exit Dfs(nUnusedSticks – 1, nLeft – len ); }
解题思路
搜索题,还要解决一个问题:如何剪枝 就本题而言,即尽可能快地发现一根拼好
的棍子需要被拆掉,以及尽量少做结果不 能成功的尝试。
剪枝1
每次开始拼第i根棍子的时候,必定选剩下的木棒 里最长的一根,作为该棍子的第一根木棒。
为len)拼在当前棍子上,然后 exit Dfs(nUnusedSticks – 1, nLeft – len ); }
Dfs的终止条件之一:
bool Dfs(int nUnusedSticks, int nLeft ) { if( nUnusedSticks = 0 and nLeft = 0 ) exit true; if( nLeft = 0 ) //一根刚刚拼完 nLeft := L; //开始拼新的一根 找一根长度不超过nLeft的木棒(假设长为len)
搜索
有顺序有策略地产生解空间的元素 每个解空间的元素表现为一定动作的执行轨迹 (trace of actions)
采用递归的策略产生解空间的元素,出口条件 轨迹已经达到终点:真解、或者伪解 轨迹不可能导出真解
搜索的过程
两个状态的集合 : 未处理完的状态 : 已处理的状态
搜索
深度优先搜索 广度优先搜索
枚举
划分解的存在范围 对范围内的元素进行逐一判断 例:求出A~I 分别对应的数字(1~9) 使得下
式成立 ABCD ×E
FGHI
枚举解法
枚举ABCDE的值,计算乘积,判断是否符 合要求。
搜索复杂的、高级的枚举
枚举: 解空间中的每个元素是一个动作(action)的 集合F
表示: 当前有nUnusedSticks根未用木棒, 而且当前正在拼的那根棍子比假定的棍子 长度短了nLeft, 那么在这种情况下能否全部 拼成功。
Dfs的基本递推关系:
bool Dfs(int nUnusedSticks, int nLeft) { ….. if( nLeft = 0 ) //一根刚刚拼完 nLeft := L; //开始拼新的一根 找一根长度不超过nLeft的木棒(假设长
即:就算由于以后的拼接失败,需要重新调整第i根 棍子的拚法,也不会考虑替换第i根棍子中的第一 根木棒(换了也没用)。如果在此情况下怎么都 无法成功,那么就要推翻第i-1根棍子的拚法。如 果不存在第i-1根棍子,那么就推翻本次假设的棍 子长度,尝试下一个长度
剪枝1
因为短木棒比较容易用来填补空缺。一根 长木棒,当然比总和相同的几根短木棒要 优先使用
Dfs递归搜索函数
Bool Dfs(int nUnusedSticks, int nLeft ) ;
Function dfs(nUnusedSticks:longint, nLeft:longint):longint
解题思路
在拼接过程中,要给用过的木棒做上标记, 以免重复使用
回溯:拼好前i根棍子,结果发现第i+1根拼 不成了,那么就要推翻第i根的拼法,重拼 第i根…..直至有可能推翻第1根棍子的拼法
解题思路
搜索题,首先要解决一个问题:按什么顺 序搜索?
把木棒按长度排序。每次选木棒的时候都 尽量先选长的。
判重:每次演化出一个状态s时,s是否属于 或者
剪枝:状态s的任意演化结果是否都属于
属于,则剪枝
演化出来的状态数量:的大小
深度优先搜索
两个状态的集合 : 未处理完的状态 : 已处理的状态
从中选择被演化状态的原则:离初态S0最远的状 态s S0到s的距离:从S0到达s使用的动作数量