题意:
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:
1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
Input
两个整数,N和K
Output
一个整数,农夫抓到牛所要花费的最小分钟数
Sample Input
5 17
Sample Output
4
第一眼看到这道题如果我不知道他是搜索的话可能就会去考虑智力题或者贪心了…但转念一想贪心是每一步都取最优解,应用不到这道题上。
看了看别的大佬的思路,思路整理如下:
首先肯定不能用深搜解,TLE是肯定的。并且广搜适合用来解决“最优解”“最短路径”“最快”等这种问题。所以方法肯定是广搜。
广搜是不停地扩展树的宽度,一层一层往下遍历。这道题农夫有三种走法,也就是说可以想象成一个三叉树(但注意bfs用的数据结构是图!!)。
首先可以想到需要的是
- quene数组(广搜标配) 搭配int head=0;int tail=1; 食用
- book数组 如果已经入过队了就不要再入一次了
然后把广搜的模板套上,会发现,这个输出不会搞… 因为三种走法的时间都是1min,那输出搜索到next==k的时候的“树”的深度-1就行。那这个“步数计算器“,就需要一个pre数组,返回父结点,设置sum++;这个其实找出了他的路径。(具体写进周总结里了)。上源代码。
//需要一个步数计数器
#include<stdio.h>
int que[1000000]={0};
int n,k;
int next;
int book[1000000]={0};
int pre[1000000]={0};//步数计算器
void step(int x){
int sum=0;
while(pre[x]){
sum++;
x=pre[x];
}
printf("%d",sum);
}
void bfs(){
if(n==k) {
printf("0");
return;//如果一开始就在一块就输出0
}
int head=0;
int tail=1;
que[1] = n;
book[n]=1;//队列的初始化
while(head != tail){
head++;
for(int i=1;i<=3;i++){
if(i==1) next=que[head]-1;
if(i==2) next=que[head]+1;
if(i==3) next=2*que[head];
if(next<=100000 && book[next]==0 && next>=0){//设置next的范围是怕陷入死循环且负数不能当做数组下标
tail++;
que[tail]=next;
book[next]=1;//把入队了的一标记
pre[tail]=head;//记录一下父结点!
if(next==k){
step(tail);
head=tail;//强行结束while循环
break;
}
}
}
}
}
int main(){
scanf("%d%d",&n,&k);
bfs();
}