luogu1588 丢失的牛
时空限制 1000ms/128MB
题目描述
FJ丢失了他的一头牛,他决定追回他的牛。已知FJ和牛在一条直线上,初始位置分别为x和y,假定牛在原地不动。FJ的行走方式很特别:他每一次可以前进一步、后退一步或者直接走到2*x的位置。计算他至少需要几步追上他的牛。
输入输出格式
输入格式:
第一行为一个整数t(≤10),表示数据组数;接下来每行包含一个两个正整数x和y(0<x,y≤10^5),分别表示FJ和牛的坐标。
输出格式:
对于每组数据,输出最少步数。
输入输出样例
输入样例#1:
1 5 17
输出样例#1:
4
代码
法一:STL队列
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 100005;
const int dx[] = {-1,1};
int T,x,y;
struct node{
int point,step;
node(){ }
node(int a,int b):point(a),step(b){ }
};
bool visit[N];
void bfs(){
fill(visit,visit+N,false); //重置标记
queue<node> q;
q.push(node(x,0)); //到x坐标0步入队
visit[x] = true;
while (!q.empty()){ //队列非空
node k=q.front(); q.pop(); //取队头,队头出队
if (k.point==y){ cout<<k.step<<endl; return; } //找到
int xx;
for (int i=0; i<2; i++){ //前进一步或后退一步
xx = k.point+dx[i]; //现在坐标
if (xx>=0 && xx<N && !visit[xx]){
q.push(node(xx,k.step+1)); //到xx坐标k.step+1步入队
visit[xx] = true;
}
}
xx = 2*k.point; //走到2倍当前坐标位置
if (xx>=0 && xx<N && !visit[xx]){
q.push(node(xx,k.step+1)); //到xx坐标k.step+1步入队
visit[xx] = true;
}
}
}
int main(){
cin>>T;
while (T--){
cin>>x>>y;
if (x>=y) cout<<x-y<<endl; //牛坐标比人小
else bfs();
}
return 0;
}
法二:手动队列
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100005;
const int dx[] = {-1,1};
int T,x,y,que[N][2],head,tail;
bool visit[N];
void bfs(){
fill(visit,visit+N,false); //重置标记
head = tail = 0; //重置队列
que[++tail][0]=x; que[tail][1]=0; //到x坐标0步入队
visit[x] = true;
while (head<tail){ //队列非空
head++; //取队头,队头出队
if (que[head][0]==y){ cout<<que[head][1]<<endl; return; } //找到
int xx;
for (int i=0; i<2; i++){ //前进一步或后退一步
xx = que[head][0]+dx[i]; //现在坐标
if (xx>=0 && xx<N && !visit[xx]){
que[++tail][0]=xx; que[tail][1]=que[head][1]+1; //到xx坐标que[head][1]+1步入队
visit[xx] = true; //入队后标记
}
}
xx = 2*que[head][0]; //走到2倍当前坐标位置
if (xx>=0 && xx<N && !visit[xx]){
que[++tail][0]=xx; que[tail][1]=que[head][1]+1; //到xx坐标que[head][1]+1步入队
visit[xx] = true;
}
}
}
int main(){
cin>>T;
while (T--){
cin>>x>>y;
if (x>=y) cout<<x-y<<endl; //牛坐标比人小
else bfs();
}
return 0;
}