题意
一个人要抓奶牛。
开始输入人和牛的位置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=…