广度优先搜索--抓住那头牛(poj 3278)

描述

农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:

1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟

假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?


输入
两个整数,N和K
输出
一个整数,农夫抓到牛所要花费的最小分钟数
样例输入
5 17
样例输出
4



广度优先搜索算法如下:(用QUEUE)

(1) 把初始节点S0放入Open表中;

(2) 如果Open表为空,则问题无解,失败退出;

(3) Open表的第一个节点取出放入Closed表,并记该节点为n;

(4) 考察节点n是否为目标节点。若是,则得到问题的解,成功退出;

(5) 若节点n不可扩展,则转第(2)步;

(6) 扩展节点n,将其不在Closed表和Open表中的子节点(判重)放入Open表的尾部,并为每一个子节点设置指向父节点的指针(或记录节点的层次),然后转第(2)步。 


先看一个广搜遍历:


#include 
#include 
#define NUM 100

using namespace std;

    //广度优先搜索算法如下:(用QUEUE)
    //(1) 把初始节点S0放入Open表中;
    //(2) 如果Open表为空,则问题无解,失败 退出;
    //(3) 把Open表的第一个节点取出放入 Closed表,并记该节点为n;
    //(4) 考察节点n是否为目标节点。若是, 则得到问题的解,成功退出;
    //(5) 若节点n不可扩展,则转第(2)步;
    //(6) 扩展节点n,将其不在Closed表和 Open表中的子节点(判重)放入Open表的尾部 ,
    //并为每一个子节点设置指向父节点的指针( 或记录节点的层次),然后转第(2)步。


int Graph[NUM][NUM];
int N,M;//顶点数和边数;
bool visit[NUM] = {false};//标记已经访问过的顶点;




void BFS(int k)
{
    visit[k] = true;
    queue q;
        //把初始节点S0放入Open表中;
    q.push(k);
        //    如果队列表为空,则问题无解,失败 退出;
    while(!q.empty()){
            //        把Open表的第一个节点取出;
        int temp = q.front();
        printf("%c ",temp+'a'-1);
        q.pop();
        for(int i = 1;i<=N;i++){
            if(Graph[temp][i]==1&&!visit[i]){
                visit[i] = true;
                q.push(i);
            }
        }

    }
}





int main()
{
    cin>>N>>M;
    for(int i =1;i<=M;i++){
        char a,b;
        cin>>a>>b;
        int x = a-'a'+1;
        int y = b-'a'+1;
        Graph[x][y] = Graph[y][x] = 1;
    }


        //针对非连通图
    for(int i = 1;i<=N;i++)
        if(!visit[i])
            BFS(i);
    cout <



   //这道题注意

//1.这种图是无法用数据结构来存储的,这是一种未知的图;不过他的顶点个数可以得到;并且是每两个顶点之间的位置直接就可以知道的,

//这是由关系来却定的,所以在入队列的时候直接就是将其找到其邻接顶点,直接就入队了,这种能直接找到邻接顶点的直接就是开始广搜

//,不需要储蓄,因为存储的目的也就是为了将每一邻接的顶点找到,如果能直接省略的储存就直接省略了,

//2,在使用广搜的时候可能要求解其中的步数,这个时候可以将入队列的类型是一个结构体,这样在入队列的时候直接就可以将其+1,就可以将

//步数计算的到;


这道题的代码:


 

#include 
#include 
#define NUM 100000

using namespace std;
int N,K;
bool visted[NUM+10];


struct Step{
    int i;
    int step;
    Step(int x,int s):i(x),step(s){};//默认构造函数;
};



void BFS()//过程和层序遍历二叉数一样的;不一样就是二叉树只有两个邻接顶点,这是确定的;
{
    queue q;

    q.push(Step(N,0));//农夫最初的位置;
    visted[N] = true;
    while(!q.empty()){
        Step s = q.front();//获取第一个顶点的值
        q.pop();
        if(s.i == K){
            cout<= 0 && !visted[s.i-1] ) {
                q.push(Step(s.i-1,s.step+1));
                visted[s.i-1] = true;
            }
            if( s.i + 1 <= NUM && !visted[s.i+1] ) {
                q.push(Step(s.i+1,s.step+1));
                visted[s.i+1] = true;
            }
            if(s.i*2<=NUM&&!visted[s.i*2]){
                q.push(Step(s.i*2,s.step+1));
                visted[s.i*2] = true;
            }
        }
    }
}



int main()
{
    cin>>N>>K;
    BFS();
    return 0;
}



ps:我的很多题是用STL来解题的,如果不只到C++STL可以先去了解怎么用,相信你会喜欢他,因为很多题目一位有了他变得更简单;




你可能感兴趣的:(算法)