近期也是学习了搜索算法,搜索被称为通用解法(虽然啥题都可以解但是也有很大的弊端就是时间!)
概念: 状态对问题在某一时刻进展情况的数学描述或者是数学抽象。
状态转移:每一个状态都是一个可能的解,状态的转移就是问题从一个状态转移到另一个状态,这样就可以进行搜索的一步步延伸直到找到需要的解。
广度优先搜索:一层一层的搜索,通过起始状态根据规则生成下一层节点遍历过所有该层节点再遍历所有下一层节点,可以利用队列的特性来操作,按顺序遍历每一层,一开始表示很不理解但是在做了一道题目之后便是理解了
Catch That Cow每个点只经过一次(经历的最早的那一次)时间就由上一状态加1即可。
附上代码
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;
int n,a[200001],b[200001];
queue<int>qq;
int bfs(int x,int s)
{
if(x>=s)
return x-s;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
b[n]=1;
int y;
while(!qq.empty()){qq.pop();}
qq.push(x);
while(!qq.empty())
{
int v=qq.front();
qq.pop();
for(int i=0;i<3;i++)
{
if(i==0)
y=2*v;
if(i==1)
y=v+1;
if(i==2)
y=v-1;
if(v<=100000&&v>=0&&b[y]==0)
{
b[y]=1;
a[y]=a[v]+1;
qq.push(y);
if(y==s)
return a[y];
}
}
}
}
int main()
{
int x,s;
while(cin>>n>>s)
{
x=bfs(n,s);
cout<<x<<endl;
}
return 0;
}
这里再附上另一种思路的代码(之前这种思路没有过以为是错的后来有明白了这里记录一下)
用第一次经过该点的步数来标记该点是否来过这里要对第一个点(起始点)进行特殊的处理用1将其标记来标记他已经走过了,因此在输出时也要把这个一剪掉(完美!)
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;
int n,a[200001];
queue<int>qq;
int bfs(int x,int s)
{
memset(a,0,sizeof(a));
int y;
while(!qq.empty()){qq.pop();}
qq.push(x);
a[x]=1;
while(!qq.empty())
{
int v=qq.front();
qq.pop();
if(v==s)
return a[v];
for(int i=0;i<3;i++)
{
if(i==0)
y=2*v;
if(i==1)
y=v+1;
if(i==2)
y=v-1;
if(y<=100000&&y>=0&&a[y]==0)
{
a[y]=a[v]+1;
qq.push(y);
}
}
}
}
int main()
{
int x,s;
while(cin>>n>>s)
{
x=bfs(n,s);
cout<<x-1<<endl;
}
return 0;
}
深度优先搜索:
深度优先搜索则是一条路走到黑走不动了(不符合条件了)就回到上一步,找别的路走,再没其他的路了就在会退一步,直到找到解。
可以用递归来实现,注意标记了来过该点之后再进行递归之后恢复现场即再将它的状态还原回去。
学习还需要更加努力仅仅是这些还是不够的需要更大量的题目来练习见得多了自然会有所体会加上自己的总结定然能获得意想不到的收获,重要的还是寻找状态的转移这一点倒是和dp有些类似,之后将回溯搜索算法继续巩固后会继续总结!