搜索一般由以下几种
- 状态空间
- 状态转移
- 起始状态
- 目标状态
上图就是个例子,下面是一个稍微修改要求的图
状态空间图一般比较大,很难在计算机中用这些。
可以转换为树来求解。
- 宽度优先搜索(BFS)
- 深度优先搜索(DFS)
emm,就不做说明了。
例题9.1
简单来说,就是一个数组(0,100000)农夫在下标n的位置,牛在下标k的位置。农夫每次要么n+1,要么n-1,要么n*2.
假设牛没有意识到农夫在追它,在原地不动,农夫最少要多久找到。
这里需要注意的是
这两个点重复了,它们仅仅是时间不同。所以说我们不必重复查找。提高效率。
这里额外补充以下,这里n的数据量是105很明显半提示那种要用logn的时间。
这里明显可以用递归,但是递归是深度优先的。并不是宽度优先。
static void BFS(int n , int k,boolean visit[]){
Queue<Status> queue = new LinkedList<Status>();
queue.offer(new Status(n,0));
visit[n] = true;
while (!queue.isEmpty()){
Status current = queue.poll();
if(current.position==k){
System.out.println(current.time);
}
for (int i = 0; i < 3; i++) {
Status next = new Status(current.position, current.time);
if(i==0){
next.position-=1;
}else if(i==1){
next.position+=1;
}else {
next.position*=2;
}
next.time+=1;
if(next.position<0 ||next.position>100000||visit[next.position]){
continue;
}
queue.offer(next);
visit[next.position]=true;
}
}
}
不是很难,利用队列的先进先出即可层次遍历。
还是要稍微注意一下队列的基本操作
Queue queue = new LinkedList();
add
remove
offer
poll
由于java语言的特性,每次最好new一个对象添加,出队得时候由于没有对象引用会自动被回收。这里要注意一点。
例题9.2
翻译过来就是,输入一个整数,输出一个能整除它的数,这个数很特别,它只包含0和1。在不超过100得数里面肯定有一个满足题目要求。
static void BFS(int n){
Queue<Long> queue = new LinkedList();
queue.offer(1l);
while (!queue.isEmpty()){
Long current = queue.poll();
if(current%n==0){
System.out.println(current);
return;
}
queue.offer(new Long(current*10));
queue.offer(new Long(current*10+1));
//满足只有01两种数得数。
}
}
很简单的啦。
例题9.3
骑士走日字,只有八种移动方式。
这里可以用递归就好。实现深度,如果再加上字典序(从左到右)
则需要这种类型的东西,(上图c++实现);
其次设计一个visited数组,和路径数组(或字符串)。
之后递归就好了。这里不过多解释。记得参数有x,y,步数,路径。哦