2971:抓住那头牛
总时间限制:
2000ms
内存限制:
65536kB
描述
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:
1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入
两个整数,N和K
输出
一个整数,农夫抓到牛所要花费的最小分钟数
样例输入
5 17
样例输出
4
下面是代码
#include<iostream>
using namespace std;
#include<cstdio>
int n, k;//n和k分别表示农夫与牛的位置
int queue[1000000] = { 0 };//队列
int front[1000000]= { 0 };//假设front[i]=j; 也就是说农夫可以花费一分钟从位置queue[j]走到位置queue[i];
int mark[1000000]= { 0 };//假设mark[i]=1;也就是说位置queue[i]已经走过 不需要再次经过
void print(int k) {
int c = 0;
while (front[k] != 0) {
c++;
k = front[k];
}
cout << c;
}
void bfs(int n, int k) {
if (n == k) {//若刚开始n==k那么直接输出0 结束
cout << 0;
return ;
}
int head = 0, tail = 1, next;//从queue[head]到queue[tail]需要一分钟 next表示queue[head]下一步能到达的位置
queue[1] = n;//queue[1] 保存初始位置
front[1] = 0;//0用来判断是否是起始位置
mark[n] = 1;//标记位置queue[n]已经到达过
while (head != tail) {
head++;//获得新的位置queue[head]
for (int i = 1; i <= 3; i++) {//三次循环得到queue[head]往后一步走的三种情况
if (i == 1)
next = queue[head] + 1;
if (i == 2)
next = queue[head] - 1;
if (i == 3)
next = queue[head] * 2;
if (next >= 0 && next <= 100000 && mark[next] != 1) {//判断next是否在位置0--100000上并且next是否经过
tail++;//为后面的位置创造一个存放的地址
mark[next] = 1;//说明next已经来过
front[tail] = head; //表示从queue[head]到queue[tail]需要一分钟
queue[tail] = next;//在队列中存放位置next;
if (next == k) {//如果到达牛的位置
print(tail);
tail = head;//已找到答案 结束循环
break;
}
}
}
}
}
int main() {
int n, k;
cin >> n >> k;
bfs(n, k);//广度优先搜索
return 0;
}
用下面这张图可以更好理解
假设我输入 5 17
5->10->9->18->17