题目(题目传送门)
Catch That Cow
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 147593 Accepted: 45350
Description
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
5 17
Sample Output
4
Hint
The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.
Source
USACO 2007 Open Silver
[Submit] [Go Back] [Status] [Discuss]
分析
牛一共有三种方式变化位置,刚开始想用贪心或者动态规划做,贪心肯定是不对的,大家可以看看这个题中给的样例是怎么来的,
5-10-9-18-17,对于10-9这个操作,他竟然往后退了一步,其实10离17还很远,应该还是往左走,不应该往右走,但是9*2=18就非常接近了,这才是最优的方法。也就是说不能单独去选择移动距离最大的方法
对于动态规划是可以的
比较简单的是广搜这个方法,这个题简单是因为这个是线性的搜索,实在一个x坐标轴上的,一般的搜索都是一个图可以上下左右走。
关于深搜
深搜其实比广搜简单,对于广搜,我们顺着一条路走到底,如果这条路走不动了,就返回上一步(return),从上一步换一个方向走,所以递归调用函数挺复杂的。
广搜就是每走到一个点,就把这个点能走的方向都走一遍,并把这些能够到达的点存到队列中,所以用到了队列这个数据结构,特点先进先出
看下面这个图
A B C D E 1
F G H I J 2
K L M N O 3
P Q R S T 4
U V W X Y 5
以M为起点,可以上下左右移动,所以可以到达HRLN,这个就是所要找的队列,然后下一个点是H,它可以到达的点是CMGI,此时注意M这个点,刚才我们已经走过了,所以要把M去掉(我们如何判断这个点走没走过呢,就用book数组进行标记),再一个要把H这个点从队列里去除,因为H这个点能到达的点都走过一遍了,这个点已经没有利用价值了,所以此时的队列就是
RLNCGI,注意顺序,下一个要走的是R这个点,走完以后的队列是LNCGIWQS,就这样可以把一个图进行模拟搜索。
代码
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<algorithm>
#include<string.h>
const int maxn=100000+6;
using namespace std;
queue<int>q;//队列
int book[maxn];//标记走没走过
int fa[maxn];//走到这个点是第几步
int main()
{
int n,k,b,sum=0;
scanf("%d%d",&n,&k);
q.push(n);
book[n]=1;
if(n!=k)//判断要去的点就是此时的点的时候不需移动
{
while(!q.empty())
{
b=q.front();//队首元素
if(book[b+1]==0&&b+1<maxn)//向右加一
{
fa[b+1]=fa[b]+1;
if(b+1==k)
{
break;
}
q.push(b+1);
book[b+1]=1;
}
if(b-1>=0&&book[b-1]==0)//向左走一步
{
fa[b-1]=fa[b]+1;
if(b-1==k)
{
break;
}
q.push(b-1);
book[b-1]=1;
}
if(b*2<maxn&&book[b*2]==0)//瞬移
{
fa[b*2]=fa[b]+1;
if(b*2==k)
{
break;
}
q.push(b*2);
book[b*2]=1;
}
q.pop();//这个点利用完了扔掉
}
}
printf("%d\n",fa[k]);
return 0;
}
易错点
1.因为可以-1,所以注意母牛的坐标要>=0;因为你标记时用到了数组,数组里面不能有负值
2.因为有+1操作,也有*2操作,所以一定要判断数组不要越界啊!
转载:https://blog.csdn.net/weixin_44554979/article/details/101303902