原文链接

前言

最开始搞 OIOIOI 的时候接触了搜索算法,后面基本上没有在练过了。若本文有误,请在讨论区指出。

本文例题链接

思想


有时,答案不只一组,可能有多个,有些情况下需要找到有特殊情况的答案。

如上图,需要找到的答案为 ans3ans3ans3 。

首先考虑 DFSDFSDFS ,一般是一搜搜到底,很有可能找到 ans1ans1ans1 。若继续查找,很有可能花费太多时间。时间效率低。

再来考虑 BFSBFSBFS ,它可以找到最近的答案 ans2ans2ans2 。若继续查找,很有可能存储状态的队列会浪费巨大空间。空间效率低

现在引出 IDDFSIDDFSIDDFS ,它通常适用于有两个条件的问题:一是它是个最优解问题,二是最优的答案深度最小。且能够快速地找到答案。

假设在搜索树中,每层树都有 333 个方案,即是搜索树为一颗 333 叉树,共 222 层, ansansans 在 333 。

先来对比 DFSDFSDFS ,搜索路径为 1−2−5−2−6−2−7−2−1−31-2-5-2-6-2-7-2-1-31−2−5−2−6−2−7−2−1−3 ,找到答案。有最坏情况,即每一个分支都是一个无底洞,若永远搜索不到答案,就会卡在里面。

再来对比 BFSBFSBFS ,搜索路径为 1−2−31-2-31−2−3 ,看起来比较短,但是队列中有 1,2,5,6,7,31,2,5,6,7,31,2,5,6,7,3 的信息,若答案更深一些,那么就会炸空间。

通过上述两个例子,可以知道 DFSDFSDFS 和 BFSBFSBFS 的局限性,但也各有千秋。结合两种算法,就有了迭代加深。首先限定一个层数,对于搜索树进行深度优先搜索。假设这个层数为 111 ,那么深搜只会搜索到 222 ,不会继续加深。首先试探性地来找答案,直到找到答案位置。很明显,上面几层的点会搜到很多遍,但时间复杂度对于 DFSDFSDFS 来说比较优,而在空间复杂度上比 BFSBFSBFS 上略胜一筹。

很容易就写出模板:

int max_depth = min_depth;
Id_Dfs( int current_depth  ,  int max_depth ) {if( current_depth > max_depth ) return ;if( 找到答案 ){ 输出答案 ; (exit(0) ;  ||  return ;) }for each ( 当前节点的儿子节点 )Id_Dfs(current_depth + 1, max_depth) ;
}
for(; ; max_depth++ ) {Id_Dfs( 0 , i ) ;
}

结合例题理解。

题目

一个与 nnn 有关的整数加成序列 <a0,a1,a2,...,am><a_0,a_1,a_2,...,a_m><a0​,a1​,a2​,...,am​> 满足以下四个条件:

  1. a0=1a_0=1a0​=1
  2. am=na_m=nam​=n
  3. a0<a1<a2<...<am−1<ama_0<a_1<a_2<...<a_{m-1}<a_ma0​<a1​<a2​<...<am−1​<am​
  4. 对于每一个 k(1≤k≤m)k(1≤k≤m)k(1≤k≤m) 都存在有两个整数 iii 和 j(0≤i,j≤k−1j(0≤i,j≤k-1j(0≤i,j≤k−1,iii 和 jjj 可以相等 )) ,使得 ak=ai+aja_k=a_i+a_jak​=ai​+aj​

你的任务是:给定一个整数 nnn ,找出符合上述四个条件的长度最小的整数加成序列。如果有多个满足要求的答案,只需要输出任意一个解即可。

思路

按照 1,2,4,8...1,2,4,8...1,2,4,8... 这样来排列,找出最少需要的次数那么最少的层数就找到了,就减少了之前做的无用功。

树上的子节点也较为好找,只需要将之前搜索到的数字,按照题意两两搭配找到下一项。

只需要按照 IDDFSIDDFSIDDFS 的规则搜索就行了。但重点在于剪枝,写在注释里的。

for(int i = nowdepth; i >= 1; i--) {for(int j = nowdepth; j >= i; j--) {//两两搭配,且答案越大越容易找到解,故而到着找if(ans[i] + ans[j] <= n && ans[i] + ans[j] > ans[nowdepth]) {//满足题意1,2两点的搜索int now;//找到下一项ans[nowdepth + 1] = now = ans[i] + ans[j]; for(int k = nowdepth + 2; k <= limit; k++)
//从nowdepth + 1这一项开始,后面最大时也就是now不停扩大2倍,若最大都达不到n,舍去不求now <<= 1;if(now < n)continue;Id_Dfs(nowdepth + 1);//搜索下一层if(flag)//找到答案return;}}
}

C++代码

#include <cstdio>
#include <cstring>
bool Quick_Read(int &N) {N = 0;int op = 1;char c = getchar();while(c < '0' || c > '9') {if(c == '-')op = -1;c = getchar();}while(c >= '0' && c <= '9') {N = (N << 1) + (N << 3) + (c ^ 48);c = getchar();}N *= op;return N != 0;
}
void Quick_Write(int N) {if(N < 0) {putchar('-');N = -N;}if(N >= 10)Quick_Write(N / 10);putchar(N % 10 + 48);
}
const int MAXN = 1e5 + 5;
int ans[MAXN];
int limit;
bool flag;
int n;
void Id_Dfs(int nowdepth) {if(nowdepth > limit || flag)//达到层数不在恋战或找到答案,直接跳出return;if(ans[nowdepth] == n) {//满足题意flag = true;return;}for(int i = nowdepth; i >= 1; i--) {for(int j = nowdepth; j >= i; j--) {//两两搭配,且答案越大越容易找到解,故而到着找if(ans[i] + ans[j] <= n && ans[i] + ans[j] > ans[nowdepth]) {//满足题意1,2两点的搜索int now;//找到下一项ans[nowdepth + 1] = now = ans[i] + ans[j];   for(int k = nowdepth + 2; k <= limit; k++)//从nowdepth + 1这一项开始,后面最大时也就是now不停扩大2倍,若最大都达不到n,舍去不求now <<= 1;if(now < n)continue;Id_Dfs(nowdepth + 1);//搜索下一层if(flag)//找到答案return;}}}
}
void Work() {for(; !flag; limit++)//直到找到答案时停止搜索Id_Dfs(1);for(int i = 1; i < limit; i++) {//输出Quick_Write(ans[i]);putchar(' ');}putchar('\n');
}
void Init() {limit = 1;int test = 1;while(test < n) {//找到最小层数test <<= 1;limit++;}ans[1] = 1;flag = false;
}
int main() {while(Quick_Read(n)) {//多组输入输出,到0为止Init();Work();}return 0;
}

高级搜索算法之迭代加深相关推荐

  1. 启发式搜索 迭代加深搜索 搜索对象的压缩存储

    常见的几种搜索算法 常见的几种搜索算法_唐宋缘明卿_cris的博客-CSDN博客_搜索算法有哪些 搜索 -- 启发式搜索 搜索 -- 启发式搜索_Alex_McAvoy的博客-CSDN博客_启发式搜索 ...

  2. C++高级搜索算法迭代加深—————骑士精神

    题目描述: 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士,且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1 ...

  3. 迭代加深搜索与埃及分数求解

    迭代加深搜索,实质上是限定下界的深度优先搜索.即首先允许深度优先搜索K层,若没有发现可行解,再将K+1后 重复以上步骤搜索,直到搜索到可行解. 在迭代加深搜索的算法中,连续的深度优先搜索被引入,每一个 ...

  4. 算法复习——迭代加深搜索(骑士精神bzoj1085)

    题目: Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位.在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标 ...

  5. C++迭代加深搜索及其例题讲解—————Addition Chains

    前言: 学习算法时,一个关键的问题是什么时候来使用它.在一些搜索问题中,使用普通的DFS可能会让你把时间浪费在深度非常大而且答案不是最优的搜索过程上,甚至有的时候DFS搜索的深度是无穷的,而BFS虽说 ...

  6. 人工智能学习:python实现迭代加深的深度优先搜索

    人工智能学习:python实现深度优先搜索算法 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN10 python版本:3.5 开发 ...

  7. 浅谈*迭代加深*深度优先搜索

    目录 算法核心概念及思想 算法的产生 概念 拯救时间的函数 例题:<加法链> 如题,由于此文章只讲"迭代加深",所以请先了解what "深度优先搜索" ...

  8. 区别:迭代加深搜索广度优先搜索

    我之前始终不明白,迭代加深的深度优先搜索和宽度优先搜索有什么区别. 路径不同 搜索问题的解,不单单是那个点的位置.数值,还包括从根节点到达目标节点所经过的路径. 虽然在初次求解的时候,迭代加深的计算步 ...

  9. DFS,BFS和迭代加深的联系与区别

    关于DFS: DFS算法是沿着搜索树的根节点,一直遍历完该搜索树之后再回溯继续搜索的一种算法.缺点是可能会出现答案在搜索树层数很浅,在靠后的子树中,但由于搜索次序需要遍历完一棵搜索树所有的节点,所以导 ...

最新文章

  1. 二值人脸对齐--Binarized Convolutional Landmark Localizers for Human Pose Estimation and Face Alignment
  2. 使用前端框架Foundation 4来帮助简化响应式设计开发
  3. 八、Java中的i++和++i到底是什么?
  4. linux命令:userdel
  5. Devoxx 2012:Java 8 Lambda和并行性,第1部分
  6. 比较难发音的英语音标音符_音素_英语发音
  7. mysql批量查询版本号最大的_mysql子查询批量找id最大的
  8. 写出高效优美的C语言代码(单片机)
  9. Python的序列Ⅰ
  10. VB ListBox 添加不重复的值
  11. 面向对象编程(二):继承
  12. SourcesTree使用手册1:与Git进行通信
  13. 程序员面试金典——18.12最大和子矩阵
  14. c语言那些细节之little-endian和big-endian
  15. 软件开发需求整理概要
  16. 拼多多总显示服务器冻僵,为什么拼多多商家后台会打不开?什么原因导致的?
  17. 翻译记忆软件-塔多思TRADO经典教程_2
  18. python xlwt写excel_Python使用xlwt写excel并设置写入格式
  19. 虚拟服务器 切换任务管理器,在远程桌面连接中使用任务管理器(转)
  20. java写俄罗斯方块难吗_用JAVA写的俄罗斯方块

热门文章

  1. QQ,浏览器,还有这些版本?
  2. html5怎么做相册影集,照片制作视频软件|狸窝照片制作视频软件 如何用照片制作视频...
  3. Tomcat7 管理员配置
  4. BT656(4:2:2)YCbCr标准规范
  5. jQuery源码分析-10事件处理-Event-事件绑定与删除-bind/unbind+live/die+delegat/undelegate
  6. 语文七年级计算机作文,我从电脑游戏中学到了语文初一作文
  7. 数组<小罗爱c语言>
  8. 暴力破解无线密码最详细教程
  9. Shiro RememberMe 反序列化漏洞
  10. 玩吃鸡时错误服务器维护,更新吃鸡时发生错误无法连接服务器 | 手游网游页游攻略大全...