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;
    }
}

 

posted @ 2017-04-19 17:50  我依旧什么都不会  阅读(386)  评论(0编辑  收藏  举报