【POJ-3287】Catch That Cow

138 阅读1分钟
题意

一个人要抓奶牛。

​ 开始输入人和牛的位置N、K。

​ 人有三种移动方法: 1、向前走一步,耗时一分钟。

​ 2、向后走一步,耗时一分钟。

​ 3、向前移动到当前位置的两倍N*2,耗时一分钟。

​ 问人抓到奶牛的最少时间(奶牛不动)

 

思想

广度优先搜索: 要时刻以树的思想看问题:初始节点为根节点,往下有三个孩子节点(即三个可选择的方案),三个孩子节点中每个孩子节点又都有三个孩子节点,故最多(因为有的孩子可能越界或重复,需舍去)有9个孩子节点,依次往下.....展开三叉树 开始对这条树进行搜索(实际上是一边建树一边搜索的) 从根节点往下遍历,满足条件就加入队列中,同时记录每条路径的长度,即树的高度。等到发现一条可行路径后,该路径的长度或者该树的高度就是走过的步数

样例
Sample Input
5 17


Sample Output
4

 



 

AC代码
#include <iostream>
#include <queue>
using namespace std;
int N,K;
int visit[100001];
int height[1000001];
queue<int> q;

int bfs(int N,int K)
{
    //如果开始点在终点右边,则只能通过每次倒退一步的方法到达终点,即需要N-K步
    if(N>=K)
        return N-K;
    //当前位置、下一步的位置
    int now,next;
    //当前位置进队列
    q.push(N);
    height[N]=0;
    //标记已走过的当前位置
    visit[N]=1;

    while(!q.empty())
    {
        //取出当前的节点,从这个节点开始搜索
        now=q.front();
        q.pop();
        //在每一个结点都朝三个方向搜索
        for(int i=-1;i<=1;i++)
        {
            //如果越界或者判重没通过,也不用回溯,因为next初值为0,在每次循环中也是实时更新的;head也会不用管,用为head是从队列中出来的,在for循环里没有被赋值,不会发生改变
            if(i!=0)
                next=now+i;
            else
                next=now*2;

            //如果越界或者重复,则放弃这条路径
            if(next>=0 && next<=100001 && visit[next]==0)
            {
                q.push(next);
                //cout<<next<<" ";
                //树的高度加1,即路径长度加1
                height[next]=height[now]+1;
               // cout<<height[next]<<endl;
               //对走过的点进行标记,很重要。
                visit[next]=1;
            }
            //如果某一步到达终点,则从根节点到这一个节点的树的高度(即长度)就是走过的步数
            if(next==K)
                return height[next];
        }
    }
}
int main()
{
    int N,K;
    cin>>N>>K;
    cout<<bfs(N,K)<<endl;
}

 

题源:poj.org/problem?id=…