概述

搜索算法是利用计算机的高性能来有目的穷举一个问题的部分或所有的可能情况,从而求出问题的解的一种方法。它在不仅仅在算法和人工智能中占有很重要的地位,而且在图论和其他数学方面有很强的实际应用背景。另外,很多算法如动态规划、贪心等都是搜索算法的扩展,这是因为这些算法找到了某些规律来进行变相剪枝而已。搜索算法考虑这三个问题即可:1. 对于一个问题,怎样快速建立状态空间;2. 提出一个合理的搜索策略;3. 简单估计考虑剪枝的时空性能和费用。


一、Depth first search(深度优先搜索)

深度优先搜索(DFS搜索)实际上就是按照深度优先的顺讯来遍历状态空间,一般递归或栈来实现,如下图所示。换句话说就是犹如走迷宫,不撞南山不回头。

其大致算法描述如下:

void DFS(int state, int depth){for(int i=1; i<=state; i++){newstate = doOperand(state);if(answer =true) cout<< answer;elseif(depth<maxdepth)DFS(newstate,depth);}
}

接下来,看一些例子:

例1:N皇后问题

在这里,如果预先将结果存入数值就ac (代码1),否则就超时(代码2)。

 1 #include <iostream>
 2 #include <string>
 3 //#include <memory.h>
 4
 5 using namespace std;
 6
 7 int q[15];
 8
 9 bool Check(int k){
10
11     for(int i=0; i<k; i++){
12         if(q[k] == q[i] || q[k]-q[i] == k-i || q[k]-q[i] == i-k)
13             return false;
14     }
15
16     return true;
17 }
18
19 int DFS(int r, int n){
20
21     if(r == n)
22         return 1;
23
24     int ans = 0;
25
26     for(q[r]=1; q[r]<=n; q[r]++){
27         if(Check(r))
28             ans += DFS(r+1, n);
29     }
30
31     return ans;
32 }
33
34 int main(){
35
36     int n;
37     //memset(q, 0, sizeof(q));
38
39     while(cin >> n && n){
40         cout << DFS(0, n)<<endl;
41     }
42
43     return 0;
44 }

代码1

 1 #include <iostream>
 2 #include <string>
 3 #include <memory.h>
 4
 5 using namespace std;
 6
 7 int q[15], res[15];
 8
 9 bool Check(int k){
10
11     for(int i=0; i<k; i++){
12         if(q[k] == q[i] || q[k]-q[i] == k-i || q[k]-q[i] == i-k)
13             return false;
14     }
15
16     return true;
17 }
18
19 int DFS(int r, int n){
20
21     if(r == n)
22         return 1;
23
24     int ans = 0;
25
26     for(q[r]=1; q[r]<=n; q[r]++){
27         if(Check(r))
28             ans += DFS(r+1, n);
29     }
30
31     return ans;
32 }
33
34 int main(){
35
36     int n;
37     //
38     for(int i=1; i<=10; i++){
39         memset(q, 0, sizeof(q));
40         res[i] = DFS(0,i);
41     }
42     while(cin >> n && n){
43         cout << res[n] <<endl;
44     }
45
46     return 0;
47 }

代码2

例2:ZOJ1711:Sum it up

据说标准答案:

 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "string"
 5 #include "algorithm"
 6 using namespace std;
 7 int Sum, Num, Son[15], Ans[15], Flag;
 8 void DFS(int p, int k, int s)
 9 {
10     int Last = -1;
11     if(s>Sum) return;
12     if(s==Sum)
13     {
14         Flag = 0;
15         for(int j=0; j<k-1; j++) cout<<Ans[j]<<"+";
16         cout<<Ans[k-1]<<endl;
17     }
18     for(int i=p; i<Num; i++)
19     {
20         if(s+Son[i] > Sum) continue;
21         if(Son[i]!=Last)
22         {
23             Last=Ans[k]=Son[i];
24             DFS(i+1, k+1, s+Son[i]);
25         }
26     }
27 }
28 int main()
29 {
30     while(cin>>Sum>>Num && (Sum+Num))
31     {
32         Flag = 1;
33         for(int i=0; i<Num; i++) cin>>Son[i];
34         cout<<"Sums of "<<Sum<<":"<<endl;
35         DFS(0, 0, 0);
36         if(Flag) cout<<"NONE"<<endl;
37     }
38 }

View Code

例3:ZOJ1104:Anagrams by Stack

例4:Prime Ring Problem / Prime Ring Problem

在ZOJ1457就超时,在HUD1016就能AC。这里用递归法给出代码

 1 #include <iostream>
 2 #include <string>
 3 #include <memory.h>
 4
 5 using namespace std;
 6
 7 int q[25], prime[45];
 8
 9 void GetPrime(){
10     bool flag;
11     prime[2] = 1;
12     for(int i=3; i<=40; i++){
13         flag = true;
14         for(int j=2; j*j <= i; j++){
15             if(i % j == 0){
16                 flag = false;
17                 break;
18             }
19         }
20         if(flag)
21             prime[i] = 1;
22     }
23 }
24
25
26 bool Check(int k){
27     if(!prime[q[k]+q[k-1]])
28         return false;
29
30     for(int i=0; i<k; i++){
31         if(q[k] == q[i])
32             return false;
33     }
34
35     return true;
36 }
37
38 void DFS(int r, int n){
39
40     if(r == n && prime[q[0]+q[n-1]]){
41         for(int i=0; i<n-1; i++){
42             cout << q[i] << " ";
43         }
44         cout << q[n-1] << endl;
45     }
46
47     for(q[r]=1; q[r]<=n; q[r]++){
48         if(Check(r))
49             DFS(r+1, n);
50     }
51 }
52
53 int main(){
54
55     int n,k;
56     memset(prime, 0, sizeof(prime));
57     GetPrime();
58
59     k =1;
60     while(cin >> n){
61         cout<<"Case "<<k<<":"<<endl;
62         memset(q, 0, sizeof(q));
63         q[0] = 1;
64         DFS(1, n);
65         k++;
66         cout << endl;
67     }
68
69     return 0;
70 }

View Code


一、Breadth First Search(广度优先搜索)

广度优先搜索(BFS搜索)实际上就是按照广度优先的顺讯来遍历状态空间,一般队列来实现,如下图所示。换句话说就是先寻找最近的东西,然后去扩大范围去寻找远的东西。

一般步骤如下:
1. 从队列中取出一个结点,检查它按照扩展规则是否能够扩展,如果能则产生一个新结点。
2. 检查新生成的结点,看它是否已在队列中存在。如果存在,则放弃该结点,然后回到第一步。否则新结点加入到队列尾
3. 检查新结点是否目标结点。如果是,搜索成功,程序结束。若不是,则回到第一步。
最终产生两种结果,找到目标或无法找到目标。广度优先能保证找到一条通向它的最佳路径。

例1. Catch That Cow

 1 #include <iostream>
 2 #include <queue>
 3 #include <string>
 4
 5 using namespace std;
 6 #define MAX 100000
 7 int step[100005], used[100005];
 8 queue<int> q;
 9
10 void BFS(int n, int k){
11
12     int head, x;
13     q.push(n);
14     used[n] = 1;
15     step[n] = 0;
16     while(!q.empty()){
17         head = q.front();
18         q.pop();
19         x = head;
20         if(head == k)
21             cout<< step[head] <<endl;
22         if(x-1>0 && !used[x-1]){
23             q.push(x-1);
24             used[x-1] = 1;
25             step[x-1] = step[x] + 1;
26         }
27         if(x+1 <= MAX && !used[x+1]){
28             q.push(x+1);
29             used[x+1] = 1;
30             step[x+1] = step[x] + 1;
31         }
32
33         if(2*x <= MAX && !used[2*x]){
34             q.push(2*x);
35             used[2*x] = 1;
36             step[2*x] = step[x] + 1;
37         }
38     }
39 }
40
41
42 int main(int argc, char *argv[])
43 {
44     int n,k;
45
46
47     while(cin>>n>>k){
48         memset(used, 0, sizeof(used));
49         memset(step, 9, sizeof(step));
50         if(n>=k)
51             cout << n-k <<endl;
52         else
53             BFS(n,k);
54     }
55     return 0;
56 }

View Code

例2. Jugs

刚开始蛮力搜索,结果Memory Limit Exceeded。代码如下:

 1 #include <iostream>
 2 #include <string>
 3 #include <queue>
 4 #include <stack>
 5
 6 using namespace std;
 7
 8 struct data{
 9     int a, b, site;
10 };
11 struct way{
12     int site, str, pre;
13 };
14 stack<way> w;
15 string s[10] = {"fill A\n","fill B\n","empty A\n", "empty B\n","pour A B\n","pour B A\n", "success"};
16 int k;
17
18 data GetJugs(data cur, int a, int b, int c){
19     data next;
20     switch(c){
21         case 0: next.a = a; next.b = cur.b; next.site = k++; break;
22         case 1: next.a = cur.a; next.b = b; next.site = k++; break;
23         case 2: next.a = 0; next.b = cur.b; next.site = k++; break;
24         case 3: next.a = cur.a; next.b = 0; next.site = k++; break;
25         case 4: next.a = (cur.a+cur.b<b)?0:(cur.a+cur.b-b); next.b = (cur.a+cur.b>b)?b:(cur.a+cur.b); next.site = k++; break;
26         case 5: next.a = (cur.a+cur.b>a)?a:(cur.a+cur.b); next.b = (cur.a+cur.b<a)?0:(cur.a+cur.b-a); next.site = k++; break;
27     }
28     return next;
29 }
30
31 void BFS(int a, int b, int target){
32     queue<data> q;
33     data next, cur;
34     way wCur;
35     cur.a = a; cur.b = 0; cur.site = k++;
36     q.push(cur);
37     wCur.str = 0; wCur.site = cur.site; wCur.pre = 0;
38     w.push(wCur);
39     cur.a = 0; cur.b = b; cur.site = k++;
40     q.push(cur);
41     wCur.str = 1; wCur.site = cur.site; wCur.pre = 1;
42     w.push(wCur);
43
44     while(!q.empty()){
45         cur = q.front();
46         q.pop();
47
48         if(cur.b == target){
49             wCur.str = 6; wCur.pre = cur.site; wCur.site = -1;
50             w.push(wCur);
51             break;
52         }
53         for(int i=0; i<=5; i++){
54             next = GetJugs(cur, a, b, i);
55             q.push(next);
56             wCur.str = i; wCur.site = next.site; wCur.pre = cur.site;
57             w.push(wCur);
58         }
59     }
60 }
61
62
63 int main(int argc, char *argv[])
64 {
65     int a,b,t;
66     way next, cur;
67     string str;
68     while(cin>>a>>b>>t){
69         k=0;
70         BFS(a,b,t);
71         if(!w.empty()){
72             cur = w.top();
73             w.pop();
74             str = s[cur.str];
75         }
76         while(!w.empty()){
77             next = w.top();
78             w.pop();
79             if(next.site == cur.pre){
80                 str = s[next.str]+str;
81                 cur = next;
82             }
83         }
84         cout <<str<<endl;
85     }
86     return 0;
87 }

View Code

由于有一些重复,需要去掉重复,因此加入jugs的数组来判断是否前面出现过,就AC了。代码如下

 1 #include <iostream>
 2 #include <string>
 3 #include <queue>
 4 #include <stack>
 5 #include <cstring>
 6
 7 using namespace std;
 8
 9 struct data{
10     int a, b, site;
11 };
12 struct way{
13     int site, str, pre;
14 };
15 stack<way> w;
16 string s[10] = {"fill A\n","fill B\n","empty A\n", "empty B\n","pour A B\n","pour B A\n", "success"};
17 int k, jug[1005][1005];
18
19 data GetJugs(data cur, int a, int b, int c){
20     data next;
21     switch(c){
22         case 0: next.a = a; next.b = cur.b; next.site = k++; break;
23         case 1: next.a = cur.a; next.b = b; next.site = k++; break;
24         case 2: next.a = 0; next.b = cur.b; next.site = k++; break;
25         case 3: next.a = cur.a; next.b = 0; next.site = k++; break;
26         case 4: next.a = (cur.a+cur.b<b)?0:(cur.a+cur.b-b); next.b = (cur.a+cur.b>b)?b:(cur.a+cur.b); next.site = k++; break;
27         case 5: next.a = (cur.a+cur.b>a)?a:(cur.a+cur.b); next.b = (cur.a+cur.b<a)?0:(cur.a+cur.b-a); next.site = k++; break;
28     }
29     return next;
30 }
31
32 void BFS(int a, int b, int target){
33     queue<data> q;
34     data next, cur;
35     way wCur;
36     cur.a = a; cur.b = 0; cur.site = k++;jug[cur.a][cur.b] = 1;
37     q.push(cur);
38     wCur.str = 0; wCur.site = cur.site; wCur.pre = 0;
39     w.push(wCur);
40     cur.a = 0; cur.b = b; cur.site = k++;jug[cur.a][cur.b] = 1;
41     q.push(cur);
42     wCur.str = 1; wCur.site = cur.site; wCur.pre = 1;
43     w.push(wCur);
44
45     while(!q.empty()){
46         cur = q.front();
47         q.pop();
48
49         if(cur.b == target){
50             wCur.str = 6; wCur.pre = cur.site; wCur.site = -1;
51             w.push(wCur);
52             break;
53         }
54         for(int i=0; i<=5; i++){
55             next = GetJugs(cur, a, b, i);
56             if(jug[next.a][next.b]) continue;
57             jug[next.a][next.b] = 1;
58             q.push(next);
59             wCur.str = i; wCur.site = next.site; wCur.pre = cur.site;
60             w.push(wCur);
61         }
62     }
63 }
64
65
66 int main(int argc, char *argv[])
67 {
68     int a,b,t;
69     way next, cur;
70     string str;
71     while(cin>>a>>b>>t){
72         k=0;
73         BFS(a,b,t);
74         memset(jug, 0, sizeof(jug));
75         if(!w.empty()){
76             cur = w.top();
77             w.pop();
78             str = s[cur.str];
79         }
80         while(!w.empty()){
81             next = w.top();
82             w.pop();
83             if(next.site == cur.pre){
84                 str = s[next.str]+str;
85                 cur = next;
86             }
87         }
88         cout <<str<<endl;
89     }
90     return 0;
91 }

View Code

还有zoj1091,1047,1103,1649,1310,1136,1530,1301

转载于:https://www.cnblogs.com/linspirit/articles/3840035.html

Search(搜索法)相关推荐

  1. 《Python程序设计》python常用的格式转换

    #字典 tinydict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'} tinydict['Age'] = 8 # 更新 tinydict['Schoo ...

  2. 【printf函数】vprintf使用参数列表(va_list)传递参数

    [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇 格式化输出函数 printf函数族功能介绍 printf参数 type(类型) flags(标志) number(宽度) precision( ...

  3. 组合搜索(combinatorial search)在算法求解中的应用

    1. 分治.动态规划的局限性 没有合适的分割方式时,就不能使用分治法: 没有合适的子问题或占用内存空间太大时,就不能用动态规划: 此时还需要回到最基本的穷举搜索算法. 穷举搜索(exhaustive ...

  4. 二分搜索法 C++代码实现 恋上数据结构笔记

    复习梗概 二分搜索法的end有两种定义方式,两种分别是什么含义? 二分搜索法end的两种定义方式分别影响了什么?(结束条件,更新指针) 二分搜索法的结束条件和更新指针两步代码? 二分搜索法的整体流程? ...

  5. 人工智能之集束搜索Beam Search Algorithm

      集束搜索是属于人工智能基础知识中的知情搜索,知情搜索是基于启发法的一种搜索方法,由爬山法-->最陡爬坡法-->最佳优先搜索法-->集束搜索,逐步优化算法 通过爬山简单来说下这几种 ...

  6. 人工智能导论(5)——搜索策略(Search Strategy)

    文章目录 一. 概述 二. 重点内容 三. 思维导图 四. 重点知识笔记 1. 概述 1.1 基本概念 1.2 状态空间图表示 2. 搜索过程及回溯策略 3. 盲目搜索 3.1 宽度优先搜索 3.1 ...

  7. 网格搜索法调参神经网络

    网格搜索法调参神经网络 通过包装 Keras 模型来使用 scikit-learn,并学习怎么使用网格搜索(grid search) - 怎样网格搜索通用神经网络参数,如学习速率(learning r ...

  8. 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS)

    广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS) 1. 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first searc ...

  9. 机器学习教程:网格搜索法交叉验证法

    机器学习教程:网格搜索法&交叉验证法 网格搜索法(Grid SearchCV) 概念 Python机器学习笔记:Grid SearchCV(网格搜索) - 战争热诚 - 博客园 GridSea ...

最新文章

  1. 《小程序个人信息保护研究报告》解读
  2. 跟人聊天的总结:为什么选择SAP
  3. JavaWeb课程复习资料(四)——创建Servlet
  4. 华为发布最强 AI 处理器昇腾 910,全场景 AI 框架 MindSpore 将开源
  5. 【SpringMVC学习11】SpringMVC中的拦截器
  6. 教大家一种迅雷下载百度云文件方法
  7. 5W1H、5W2H 分析法
  8. 关于电脑登录微信会出现闪(跳)黑屏的处理办法
  9. _crol_和左移的区别
  10. 正态分布是离散分布还是连续分布_正态分布,谁与争峰
  11. linux的lilo,深入Linux的LILO
  12. SequoiaDB 巨杉数据库产品下载
  13. 科研人必备英语改写神器——PARAPHRASER多语言改写
  14. 2022-2028年中国棉花采摘机行业市场调查研究及投资策略研究报告
  15. kubernetes的DevOps业务(七):Jenkins,GitLab,Harbor,Tekton,GitOps
  16. QQ群课堂无法打开和加入
  17. MySQL多表查询练习题
  18. 高效程序员的狂暴之路
  19. linux 证书文件权限,Linux运维之道之admin1.4(权限和归属,LDAP认证)
  20. Chapter 19 稳恒磁场

热门文章

  1. 大数据0404-java动态代理
  2. PDF注释或备注字体大小如何改变?
  3. 关于change事件的用法
  4. Spring Enable 是什么?
  5. 正确开启Mockjs的三种姿势:入门参考(一)
  6. UML类图中各种箭头和线条的含义和用法(转)
  7. ppt点击文字出现图片,再次点击消失
  8. 花生日记怎么做代理?花生日记官方邀请码AZR9NNO
  9. html侧边栏添加滚动条,侧边栏滚动条
  10. pdf转换jpg需要用的软件