题目
说明
有一天,大雄和他的伙伴们想穿越时空进行探险,可是时光机却出了一点故障,只能进行有限的时空穿越操作。大雄他们需要从现在出发,到达一个目标时间点进行探险,结束后再返回到现在,他们希望尽可能减少时光机的操作次数,你能帮助他们吗?
假设大雄和他的伙伴们出发的时间点(现在)为 S(0 < S < 1,000,000),希望到达的时间点(目标)为 T(0 < T < 1,000,000),已知时光机可以进行如下的时空穿越操作(X 为正整数):
可以从任意时刻X穿越到 X+1 或者 X-1 时刻
可以从任意时刻X穿越到 X * 2 时刻
当 X 为偶数时,可以从 X 时刻穿越到 X/2 时刻
请问,大雄和他的伙伴们从 S 时刻出发,先到达 T 时刻,再回到 S 时刻最少需要多少次时空穿越操作?
输入格式
输入的第一个数是一个正整数 N,表示测试数据一共有 N 组(0 < N < 20)。之后有 N 行,每一行包含两个正整数 S 和 T,表示出发和到达时间点。
保证 S != T
输出格式
输出包括N行,每一行一个正整数,表示每组测试数据对应的最少时光机操作次数。
样例
输入数据 1
2
5 17
4 8
输出数据 1
8
2
提示
对于 S=5,T=17:
操作如下:5->4->8->16->17->16->8->4->5
对于 S=4,T=8:操作如下:4->8->4
思路
建议先做信奥一本通1253抓住那头牛。
典型的数轴bfs问题
大雄和他的伙伴们可以从x 走到x ± 1 或2x或x/2,请问农夫大雄和他的伙伴们最少移动多少次就能到达t时刻。
深搜很有可能会找不到答案。而且不一定要搜到底,所以就想到广搜,求最少步数。
把当前能到达的位置加入队列,对于每个位置按次序往四个方向加入队列,然后用一个vis判断是否走过,当走到目标点时,输出步数。
注意:在这里因为是往返2次,所以要bfs2次,一次是bfs(n,k) ,一次是bfs(k,n)
ps:
代码
#include <bits/stdc++.h>
using namespace std;
int vis[1000010],dx[5];
int n,k;
queue <int> q;
int bfs(int x,int k)
{
while(!q.empty()) q.pop();
memset(vis,0,sizeof(vis));
vis[x] = 1;
q.push(x);
while(!q.empty())
{
int t = q.front();
if(t == k) return vis[t];
dx[0] = t + 1;
dx[1] = t - 1;
dx[2] = t * 2;
int p = 3;
if(t % 2 == 0) dx[3] = t / 2,p++;
for(int i = 0; i < p; i++)
{
if(dx[i] <= 1000000 && dx[i] >= 0 && vis[dx[i]] == 0)
{
q.push(dx[i]);
vis[dx[i]] = vis[t] + 1;
}
}
q.pop();
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>k;
cout<<(bfs(n,k) - 1) + (bfs(k,n) - 1)<<'\n';
}
return 0;
}