宽度优先搜索
从起点开始,依次搜索其临近的邻居结点,再按照访问顺序访问该结点的临近结点,直到搜索完毕整个空间。
- 农夫约翰被告知逃跑奶牛所在的位置,希望立刻抓住。约翰刚开始站在N,奶牛站在同一直线的K,约翰有两种方式:步行和传送:步行:1分钟内从任意一个点X移动到X+1或者X-1;传送:1分钟内从任意一个点X移动到2X;假设奶牛不动。约翰需要多长时间才能追上他。
输入5 17;输出4。
#include<iostream>
#include<string>
#include<queue>
using namespace std;
const int maxn = 100001;
struct Status{
int n,t;
Status(int n,int t):n(n),t(t){}
};
bool visit[maxn];
int BFS(int n,int k){
queue<Status>m;
m.push(Status(n,0));
visit[n]=true;
while(!m.empty()){
Status current = m.front();
m.pop();
if(current.n == k){
return current.t;
}
for(int i=0;i<3;i++){
Status next(current.n,current.t+1);
cout<<next.n<<' '<<next.t<<' '<<visit[next.n]<<endl;
if(i==0){
next.n+=1;
}else if(i==1){
next.n-=1;
}else{
next.n*=2;
}
if(next.n<0 || next.n>maxn || visit[next.n]){
continue;
}
m.push(next);
visit[next.n] = true;
}
}
}
int main(){
int n,k;
cin>>n>>k;
cout<<BFS(n,k)<<endl;
return 0;
}
总结:
- 状态。确定问题的状态,通过状态的扩展,遍历所有状态,找到最优解。
- 状态扩展方式。尽可能的扩展状态,并对先扩展得到的状态进行下一次状态扩展。
- 有效状态。有些状态可以设为标记,不需要再次扩展,直接舍弃。
- 队列。为了将得到的状态优先扩展,可以插入队列,每次扩展使用队头元素进行扩展。
- 标记。使用标记判断哪些有效,哪些无效。也就是visit[i] = true。
- 有效状态数。估算有效状态是否在题目允许的范围内。
- 最优。适合求解最优值问题,因为搜索到的状态总是按照某个关键字递增。一旦出现最少、最短、最优等关键字考虑宽度搜索。
深度优先搜索
这是我之前写的一篇关于DFS的文章,纯白话,希望可以帮助各位理解
常常使用递归策略来解决DFS问题,我们使用DFS一般是为了知道是否有解而非求出最优解。