题目描述
【题目描述】
有一只鸡和一条狗,他们在一条线上,鸡的位置在点N处,狗在点M处,鸡和狗约定,狗站
那不动,鸡去找狗。可以一次向左或向右走一步,也可一次飞到原来所在位置的2倍处。鸡
飞一次和走一步时间相同。为了不让狗等得着急,鸡最快多长时间能到狗的位置。
【输入描述】
多组测试数据,每组一行N,M(0<=N,M<=100000).
【输出描述】
输出鸡到狗位置的最短时间.
【用例输入】
5 17
【用例输出】
4
问题分析
- 我们用一维坐标来表示鸡和狗的位置
- 按照用例鸡在5这个点,狗在17这个点
- 那么飞一次就能到的点为4,6,10
- 飞两次就能到的点为3,8,7,12,9,11,20
- 飞三次就能到的点为2,16,14,13,24,18,22,19,21,40
- 飞四次就能到的点为1,15,17,32,28,26,23,25,48,36,22,38,42,39,41,80
- 那么飞到17这个点只需要4次
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/85b5ee72b9363ef101d2223ddb4c0ca3.png#pic_center)
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
4 | 3 | 2 | 1 | 0 | 1 | 2 | 2 | 2 | 1 | 2 | 2 | 3 | 3 | 4 | 3 | 4 | 3 |
设计分析
- 设计思想我们采用 入队 的方式
- 开始我们把鸡所在的点5放入队列,并记录飞行时间为0
- 取出队列中的第一个点,并判断是否到达狗的位置,
- 如果到达了,返回飞行时间,如果没有到达,那么飞行一次(往前一步、往后一步或两倍处)
- 飞一次所到达的点4,6,10,并记录飞行的时间为1,依次把这些点放入队列
- 飞两次所到达的点3,8,7,12,9,11,20,并记录飞行的时间为2,依次把这些点放入队列
- 飞三次所到达的点2,16,14,13,24,18,22,19,21,40,并记录飞行的时间为3,依次把这些点放入队列
- 飞四次所到达的点1,15,17,32,28,26,23,25,48,36,22,38,42,39,41,80,
- 并记录飞行的时间为4,依次把这些点放入队列
- 此时已经 到达 狗的位置
参考代码
#include <bits/stdc++.h>
using namespace std;
struct Node {
int x;
int s;
};
int vis[100010];
int n, m;
int bfs() {
queue<Node> q;
Node root;
root.x = n;
root.s = 0;
q.push(root);
vis[n] = 1;
while (!q.empty()) {
Node p = q.front();
q.pop();
if (p.x == m) {
return p.s;
}
int tx = p.x + 1;
if (tx >= 0 && tx <= 100000 && !vis[tx]) {
Node su;
su.x = tx;
su.s = p.s + 1;
q.push(su);
vis[tx] = 1;
}
tx = p.x - 1;
if (tx >= 0 && tx <= 100000 && !vis[tx]) {
Node su;
su.x = tx;
su.s = p.s + 1;
q.push(su);
vis[tx] = 1;
}
tx = 2 * p.x;
if (tx >= 0 && tx <= 100000 && !vis[tx]) {
Node su;
su.x = tx;
su.s = p.s + 1;
q.push(su);
vis[tx] = 1;
}
}
}
int main() {
while (cin >> n >> m) {
memset(vis, 0, sizeof(vis));
cout << bfs() << "\n";
}
return 0;
}