Catch That Cow
题目描述:
Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
- Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
- Teleporting: FJ can move from any point X to the point 2 × X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?
Input:
Line 1: Two space-separated integers: N and K
Output:
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
Sample Input:
Sample Output:
Hint(提示):
题目大意:
有一个养牛场,主人发现其中有一头牛的逃跑了,他要去追回这头牛,抓住这只逃跑的牛,牛将会在那个地方不动,等着主人来抓,主人有3种移动方式,每种移动方式都以分钟为单位,有走一步,退一步,传送。这里传送指的是当前位置是4,你只能传送2倍后的位置就是8。
题目输入N,K,分别是主人和牛的位置,要求你输出最少分钟抓到这只逃跑的牛。
思路分析:
这里有2种角度,可以从人抓牛,或者牛去追人来去思考,如果人去抓牛的话,如果是第一种人抓牛可以用枚举加dfs去做,但是我不会,所以我选择了第二种,牛追人,可以用简单的递归加DFS去写就能写出来,牛去追人的话可以看成这样。
假设N<K的时候,就只能走一种路线就是退着走,用了k-m分钟
假设N>K的时候,分2种情况,第一种:如果K%2=0,这里继续细分3种情况,当m==k/2的时候,说明直接一步传送就行,当m<k/2的时候,继续递归令k=k/2,因为牛缩减一半,要用1分钟传送,所以要加1,剩下减去就行了,当m>k/2的时候,要比较2种方式所用的最短时间,一种直接用k-m的方式所用时间,一种用m-k/2+1所用的时间。
第二种:当k%2!=0,先将牛先走一步或者退一步,将其变成偶数,继续以下递归,并且判断先走一步和退一步接下来递归所用时间谁最少。
这里要注意m=0的时候,一旦m=0,必须要自增让其变成1,去递归,要不然WA。
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
int LemonDFS(int m,int k)
{
if(m>=k)//当m>k,说明只能退者走,这一种方式
{
return m-k;
}
if(k%2==0)//如果k%2==0
{
if(m<k/2)//如果m小于k/2,将牛的位置缩小一半继续递归
{
return LemonDFS(m,k/2)+1;//这里加1,是因为牛缩小一半,用了传送。所以加1分钟
}
else if(m==k/2)//m==k/2
{
return 1;//直接用传送这一步,花费一分钟
}
else if(m>k/2)//如果m>k/2
{
return min(1+m-k/2,k-m);//这里有2种行走方式,一种是牛的位置减半,然后用m去
//减去k/2,一步一步走过去,或者直接用k-m计算2者的所要的min。
}
}
else
//如果k%2!=0,那么将其多走一步,或者少走一步,然后继续递归
//因为奇数加1或者减1,必然是偶数,k%2==0,继续递归找出满足条件。
return min(LemonDFS(m,k+1),LemonDFS(m,k-1))+1;//这里加1,是因为增了一步和减了一步,
//多用了1分钟,这里比较是多走一步还是少走一步,所用的时间最少用了min函数来找
}
int main()
{
int flag=0;
int m,k;
scanf("%d %d",&m,&k);
if(m==0)//这里注意,题目没说m不能等于0,当m=0,必须要自行加1
{
flag=1;
}
printf("%d",LemonDFS(m+flag,k)+flag);//flag为min数,m=0的时候,自行加一分钟。
}