搜索分析(DFS、BFS、递归、记忆化搜索)

搜索分析(DFS、BFS、递归、记忆化搜索)

1、线性查找

在数组a[]={0,1,2,3,4,5,6,7,8,9,10}中查找1这个元素。

(1)普通搜索方法,一个循环从0到10搜索,这里略。

(2)递归(从中间向两边)

 1 //递归一定要写成记忆化递归
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 bool vis[11];
 5 int count1=0;
 6
 7 void search(int n){
 8     count1++;
 9     if(n>10||n<0||vis[n]){
10         //cout<<"back"<<endl;
11     }
12     else if(n==1){
13         vis[n]=true;
14         cout<<"find"<<endl;
15     }
16     else {
17         vis[n]=true;
18         search(n-1);
19         search(n+1);
20
21     }
22 }
23
24 int main(){
25     int a[]={0,1,2,3,4,5,6,7,8,9,10};
26     search(9);
27     cout<<count1<<endl;
28     return 0;
29
30 } 

递归(从中间到两边)

这种方法一定要加标记数组,不然会出现死循环。

其中一个死循环:

search(9)->search(8)->search(9)

而这样的死循环太多了。

其实分析的时候直接把递归的树形图画出来就好了,直观而且方便。

这样带有标记数组的递归,本质上就是记忆化递归。

所以这种环形的递归都可以写成记忆化递归。

(3)递归(从后面向前面)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 int count1=0;
 5
 6 void search(int n){
 7     count1++;
 8     if(n>10||n<0){
 9     }
10     else if(n==1){
11         cout<<"find"<<endl;
12     }
13     else {
14         search(n-1);
15     }
16 }
17
18 int main(){
19     int a[]={0,1,2,3,4,5,6,7,8,9,10};
20     search(10);
21     cout<<count1<<endl;
22     return 0;
23
24 } 

递归(从后面向前面)

这种方法是不需要标记数组的,因为递归是线性的,而不是环形的,递归之间没有交叉,不会造成重复访问。

这种和求阶乘的是一样的。

(4)BFS(从中间向两边)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 bool vis[11];
 4 int count1=0;
 5 queue<int> que;
 6
 7 void searchBFS(int n){
 8     que.push(n);
 9     while(!que.empty()){
10         count1++;
11         cout<<"count1:"<<count1<<endl;
12
13         int tmp=que.front();
14         que.pop();
15         vis[tmp]=true;
16         cout<<"tmp:"<<tmp<<endl;
17         if(tmp==1) {
18             cout<<"find"<<endl;
19             return ;
20         }
21         else{
22             if(tmp-1>=0&&!vis[tmp-1]) que.push(tmp-1);
23             if(tmp+1<=10&&!vis[tmp+1]) que.push(tmp+1);
24         }
25     }
26 }
27
28 int main(){
29     int a[]={0,1,2,3,4,5,6,7,8,9,10};
30     searchBFS(9);
31     cout<<count1<<endl;
32     return 0;
33
34 } 

BFS(从中间向两边)

这种BFS也是一定要带标记数组的,所以也可以写成记忆化。

这种BFS如果不带标记数组的话,也是可以得到正确答案的,不过会重复算很多算过的东西。

例如:9 8 10 7 9 9 6 8 8 10 8 10 .........

比如说上面的9就访问了很多次,而由于队列FIFO的特性,所以虽然重复算很多次,还是会得到正确答案。

因为7、6那一支会逐渐到1的。

当然,BFS也可以直接写成线性的,这样也是不需要标记数组的。

其实还是那样,把情况的树形图画出来就很舒服了,直观方便。

二、阶乘

(1)普通求阶乘方法:略。

(2)阶乘的递归实现DFS

阶乘的递归实现

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int jiechen(int n){
 4     if(n==1) return 1;
 5     else{
 6         return n*jiechen(n-1);
 7     }
 8 }
 9 int main(){
10     cout<<jiechen(8)<<endl;
11     return 0;
12 } 

DFS

从尾直接算到头,不需要标记数组

(2)阶乘的栈实现

 1 /*
 2 伪码:
 3 我们求f(n),f(n)入栈
 4 在栈不空的情况下(下面循环)
 5 出栈
 6 f(n)=f(n-1)*n
 7 如果f(n-1)没有被求出来,直接入栈
 8 */
 9
10 //对数组而言,我们操作的肯定是下标,而一定不是数组元素的值
11 #include <bits/stdc++.h>
12 using namespace std;
13 stack<int> sta;
14 int a[15];
15
16 int jiechen(int n){
17     a[1]=1;
18     sta.push(n);
19     while(!sta.empty()){
20         int tmp=sta.top();
21         sta.pop();
22         //如果a[tmp-1]被计算了
23         if(a[tmp-1]!=0){
24             a[tmp]=a[tmp-1]*tmp;
25             cout<<tmp<<" "<<a[tmp]<<endl;
26         }
27         else{
28             sta.push(tmp);
29             sta.push(tmp-1);
30         }
31     }
32     return a[8];
33 }
34
35 int main(){
36     cout<<jiechen(8)<<endl;
37     return 0;
38 } 

阶乘的栈实现

对数组而言,我们操作(存储进栈或者队列或者其它操作)的肯定是下标,而一定不是数组元素的值 

其实栈实现和递归实现是一样的,因为递归在计算机内部就是用栈实现的。

时间: 2024-08-06 11:58:40

搜索分析(DFS、BFS、递归、记忆化搜索)的相关文章

Zoj 1671 Walking Ant(BFS+优先队列||记忆化搜索)

Walking Ant Time Limit: 2 Seconds Memory Limit: 65536 KB 点击打开链接 Ants are quite diligent. They sometimes build their nests beneath flagstones. Here, an ant is walking in a rectangular area tiled with square flagstones, seeking the only hole leading to

HDU 1428 漫步校园 (BFS+优先队列+记忆化搜索)

题目地址:HDU 1428 先用BFS+优先队列求出所有点到机房的最短距离,然后用记忆化搜索去搜. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #incl

HDU 5024 Wang Xifeng&#39;s Little Plot (枚举 + DFS记忆化搜索)

Wang Xifeng's Little Plot Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 513    Accepted Submission(s): 338 Problem Description <Dream of the Red Chamber>(also <The Story of the Stone>)

[hdoj]1244记忆化搜索

题解参考:http://www.cnblogs.com/peaceful-andy/archive/2012/08/14/2638907.html 很久很久以前……我一直以为记忆化搜索就是dp,dp就是记忆化搜索……多么悲哀的认识…… 动态规划是“填表格”的顺序依次递推,记忆化搜索说白了就是搜索的一种,树型,二者的相同点就是,边运行边记忆,对于计算过的都存起来,不再重复计算. 1 #include <iostream> 2 using namespace std; 3 4 const int

路径方案数_mod_SPFA_记忆化搜索_C++

本文含有原创题,涉及版权利益问题,严禁转载,违者追究法律责任 本来是写个 DP 分分钟就 A 了,结果老师要我们写记忆化搜索(无奈脸) 算啦,随手一改又是一个标准的记忆化搜索(目测好像是记忆化搜索容易码一些,而且跑得快一些) 话说不取模也可以A,数据太水 很水的题吧,先 SPFA 跑一遍 2 的最短路,然后记忆化搜索统计方案 不难证明在加上最短路的限制条件后,图变成了一个 DAG 证明:首先有向是显然的,不可能存在两点 x,y,它们的最短路 d[x]>d[y] 又 d[x]<d[y] 若存在一

蓝桥杯历届试题 地宫取宝 dp or 记忆化搜索

问题描述 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签. 地宫的入口在左上角,出口在右下角. 小明被带到地宫的入口,国王要求他只能向右或向下行走. 走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿). 当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明. 请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝. 输入格式 输入一行3个整数,用空格分开:n

ACM-ICPC 2018 徐州赛区网络预赛 B BE, GE or NE(博弈,记忆化搜索)

链接https://nanti.jisuanke.com/t/31454 思路 开始没读懂题,也没注意看数据范围(1000*200的状态,记忆化搜索随便搞) 用记忆化搜索处理出来每个状态的胜负情况 因为每个人都会选择最优的,因此记忆化搜索的过程其实就是在模拟两个人每一步决策所带来的胜负情况, 只要返回一个必胜,就直接返回(因为会选择最优) 然后在没有返回必胜的状态下,有平局就选择平局,没有平局就只能输了 #include<bits/stdc++.h> #define st 100 #defin

hdu1428 记忆化搜索(BFS预处理最短路径和+DP+DFS)

题意:有一块 n * n 大小的方形区域,要从左上角 (1,1)走到右下角(n,n),每个格子都有通过所需的时间,并且每次所走的下一格到终点的最短时间必须比当前格子走到重点的最短时间短,问一共有多少种走法. 这道题还是很明显的 DP 的,而且鉴于走到相邻格点可以上下左右走,所以我很快就锁定了记忆化搜索这种 DP 方式,但是事实上我的思路大方向的确没有错误,但是我仍然没有很好地挖掘题目的信息.我的想法是,某点到结尾的最短距离我可以转化成到起始点的最短距离,这样我就能从开头的点开始遍历,并且在遍历的

HDU 1428 漫步校园 (BFS + 记忆化搜索)

漫步校园 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3360    Accepted Submission(s): 1009 Problem Description LL最近沉迷于AC不能自拔,每天寝室.机房两点一线.由于长时间坐在电脑边,缺乏运动.他决定充分利用每次从寝室到机房的时间,在校园里散散步.整个HDU校园呈方形布局,可