BFS· Catch That Cow (HDU_2717)
BFS简析:
BFS(宽度优先搜索),主要搜索方法是一步一步的找,从搜索起点开始, 凡是能从上一处一步到达且满足遍历条件的,便在上一处的基础上步数加一。
而且从起点开始,它的下一步能到的点全部搜索完之后,才会进入下一层的搜索, 比如迷宫问题:标记起点的步数为0,凡是从起点开始,下一步能够到达的点,
标记步数为1,直到完成了步数为1的点的搜索,那么我就遍历所有步数为一的点,找出所有步数为2的点之后,再对步数为2的点进行遍历,找到步数为三的点,
如此往复,直到走到终点,退出寻找。
这个算法实现用到了队列的思想,每找到一个点,便立即存入队列,这样就不会存在我上一步的点还没完成遍历,就已经开始进行下一步的遍历这种尴尬的情况了,
因为肯定是现将同一层的压入队列,再压入下一层的。而且一定要避免回溯,不能将已经遍历过的点,再次遍历,不然一定会进入死循环!
下面是例题:
(HDU_2717)
大意是,输入两个数(大于0,小于100,0000),第一个数是“起点”,从这个数开始,一直进行下面三种操作,知道达到“终点”,也就是第二个输入的数。
第一种操作:在被操作数加一
第二种操作:在被操作数减一
第三种操作:在被操作数乘以二
输出只有一个数,那就是执行了多少次操作,输出这个次数,且认为
这个题,理解了BFS之后应该就能想到做法:
先开一个队列和一个数组,数组存放到达下标数的步数,并先将数组元素全部初始化为0,将起点数压入队列,如果三种操作都能执行(即操作后不会超出[0,1000000],
而且操作后的数没有出现过,即避免回溯),那么将操作后的数字对应的数组元素在操作前的基础上加一(即步数加一),找到终点后退出。
下面是代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cctype> #include <string> #include <cstring> #include <vector> #include <set> #include <map> #include <queue> #include <iterator> #define N 1000005 using namespace std; int b[N]; bool f( int x ){ if( x <0 || x > N-5 || b[x] ) return false; return true;} void bfs( int n, int m ) { queue< int > a; a.push( n ); while( a.size() ) { int k = a.front(); a.pop(); if( k == m )break; if( f( k-1) ) { a.push( k-1 ); b[k-1] = b[k] + 1; } if( f(k+1) ) { a.push( k+1 ); b[k+1] = b[k] + 1; } if( f( k*2 ) ) { a.push( k*2 ); b[k*2] = b[k] + 1; } } } main() { int n, m; while( cin >> n >> m ) { memset( b, 0, sizeof(b) ); bfs( n, m ); cout << b[m] << endl; } }