ACM学习历程29——搜索算法
来源:互联网 发布:翻译软件 编辑:程序博客网 时间:2024/06/11 14:13
搜索算法是利用计算机的高性能来有目的地穷举一个问题的部分或所有的可能情况,从而求出问题的解的一种方法。搜索过程实际上是根据初始条件和扩展规则构造一棵解答树并寻找符合目标状态的节点的过程。涉及到的概念包括:状态、状态转移、搜索树、状态空间、可行解、最优解。
一、相关概念
状态:对问题以及事物状态在某一发展阶段的数学描述。
状态转移:问题从一种状态转移到另一种状态的操作。
搜索树:以阶段中每一个状态作为一个点,状态之间的转移作为边,形成一个隐式图。
其中我们把初始状态看做根。那么我们的搜索过程实际上就是在对这个树的结点做遍历。这棵树也可以称为状态空间。
二、搜索算法分类
枚举算法:最直接的搜索方法,列举问题的所有状态.然后从中找出问题的解。
广度优先搜索(BFS):从初始状态开始,通过规则来生成第一层结点,同时检查生成结点中是否有目标结点.若没有则生成下一层接点,并检查是否有目标结点。广度优先搜索通常采用队列存储,每次扩展时都会扩展当前结点的所有子结点。
深度优先搜索(DFS):从初始结点开始扩展,按照某中顺序不断的向下扩展,直到找到目标状态或者是无法继续扩展。深度优先搜索通常用到堆栈存储,当前节点为下一次扩展结点的父节点。
双向广度优先搜索
A*算法
回溯算法
三、简单搜索算法举例
3.1 油田合并
问题描述:某石油公司发现了一个油田。该油田由n*m个单元组成的矩形,有些单元里有石油,有些则没有。单元油田可以通过上,下,左或右连通。在一个单元油田里架设一台采油机,它可以把和该单元油田相连的单元油田的石油采完。该公司想知道最少需要架设几台采油机能把所有的石油采完。
输入:输入2个正整数n,m(1<=n,m<=50)。接着有n行,每行有m个字符。'@'表示该单元有石油,'*'则表示该单元没有石油。
输出:对于每组测试,输出最少需要架设几台采油机。
解答思路:(1)建立数组,用来存储油田分布状态;(2)建立数组,用来存储采油机安装的状态;(3)某一点是否可以放采油机取决于,此地是否有油井,并且,此地的上和左,是否架设了油井,如果架设,本地不再需要,如若没有,在本地放采油机;(4)如果可以放采油机,我们就在原有采油机的基础上再加1。
解答代码:
#include<iostream>#include<string>#include<cstdio>using namespace std;int dfs(int t,int j);char data[51][51];//油田分布情况int flag[51][51];//标记油田int main(){int i,j,n,m;while(scanf("%d%d",&n,&m)!=EOF){int count=0;memset(flag,0,sizeof(flag));for(i=0;i<n;i++)scanf("%s",data[i]);for(i=0;i<n;i++){for(j=0;j<m;j++)if(data[i][j]=='@')count+=dfs(i,j);}printf("%d\n",count);}return 0;}int dfs(int i,int j){flag[i][j]=1;if(i-1>=0 && j-1>=0){if(flag[i-1][j]==1 || flag[i][j-1]==1)return 0;}else if(i-1<0 && j-1>=0){if(flag[i][j-1]==1)return 0;}else if(i-1>=0 && j-1<0){if(flag[i-1][j]==1)return 0;}return 1;}运行结果:
3.2 老鼠走迷宫:老鼠的走法有上、左、下、右四个方向,在每前进一格之后就选一个方向前进,无法前进时退回选择下一个可前进方向,如此在阵列中依序测试四个方向,直到走到出口为止。
解答代码:#include<iostream>#include<fstream>#define Row 7#define Col 7using namespace std;int m[Row][Col]={{2, 2, 2, 2, 2, 2, 2}, {2, 0, 0, 0, 0, 0, 2}, {2, 0, 2, 0, 0, 0, 2}, {2, 0, 0, 2, 0, 2, 2}, {2, 2, 0, 2, 0, 2, 2}, {2, 0, 0, 0, 0, 0, 2}, {2, 2, 2, 2, 2, 2, 2}};int x=1,y=1,xx=5,yy=5;int sum=0;void find(int x,int y);void output();//ofstream fout("estdout_2.pc2",ios::app);int main(){int i,j;for(i=0;i<Row;i++){for(j=0;j<Col;j++){if(m[i][j]==2)cout<<"█";else cout<<" ";}cout<<endl;}cout<<endl<<endl; find(1,1); cout<<"所有走法:"<<sum<<endl;return 0;}void find(int x,int y){ int t=m[x][y];m[x][y]=1; if(x==5&&y==5){sum++;output();}if(m[x+1][y]==0){find(x+1,y);}if(m[x-1][y]==0){find(x-1,y);}if(m[x][y+1]==0){find(x,y+1);}if(m[x][y-1]==0){find(x,y-1);}m[x][y]=t;return ;}void output(){ int i,j;for(i=0;i<Row;i++){for(j=0;j<Col;j++){if(m[i][j]==2){cout<<"█";}else if(m[i][j]==0){cout<<" ";}else{cout<<"◇";}}cout<<endl;}cout<<endl;}运行结果:
- ACM学习历程29——搜索算法
- ACM学习历程26——KMP算法
- ACM学习历程30——回溯算法
- ACM学习历程5——算法设计中常用的函数
- ACM学习历程1——输入输出语句
- ACM学习历程4——STL的使用
- ACM学习历程6——Vector向量容器
- ACM学习历程8——Vector应用
- ACM学习历程10——set集合容器
- ACM学习历程12——Map映照容器
- ACM学习历程13——multimap集合容器
- ACM学习历程17——bitset位集合容器
- ACM学习历程18——stack堆栈容器
- ACM学习历程21——各种排列组合问题
- ACM学习历程22——进制转换
- ACM学习历程23——最小周期串问题
- ACM学习历程24——最大回文子串
- ACM学习历程25——高精度四则运算
- POJ1804-Brainman
- c++内存地址运算
- AE、PR视频制作遇到的问题
- git学习总结
- Java绘制登陆验证码
- ACM学习历程29——搜索算法
- 明明是原创的
- Spark2.0机器学习系列之8: 聚类(k-means,Bisecting k-means,Streaming k-means)
- JAVA进阶之旅(一)——增强for循环,基本数据类型的自动拆箱与装箱,享元设计模式,枚举的概述,枚举的应用,枚举的构造方法,枚举的抽象方法
- 模仿QQ运动item的界面
- 【例】系统顺序图、操作契约、领域模型图
- 一些有用的网站收藏
- web.xml listener、filter、servlet详解
- Debian 8 安装 shadowsocks