poj3278-Catch That Cow 【bfs】

http://poj.org/problem?id=3278

Catch That Cow
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 52463   Accepted: 16451

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 - 1 or + 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.
 
 
 
题解:最短路,第一想法是bfs,简单易操作。这里需要说明一下就是,这道题目的边界不需要扩充,理由嘛,看下面0ms代码的注释吧。再次强调,STL少用,这里再次验证了其效率的低下。
代码一:【127ms】bfs暴搜+STL里的queue:
 1 #include <fstream>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <cmath>
 7 #include <cstdlib>
 8 #include <queue>
 9 
10 using namespace std;
11 
12 #define PI acos(-1.0)
13 #define EPS 1e-10
14 #define lll __int64
15 #define ll long long
16 #define INF 0x7fffffff
17 
18 queue<pair<int,int> > qu;
19 bool b[100002];
20 
21 inline bool Check(int x);
22 int Bfs(int r1,int r2);
23 
24 int main(){
25     //freopen("D:\input.in","r",stdin);
26     //freopen("D:\output.out","w",stdout);
27     int r1,r2;
28     scanf("%d %d",&r1,&r2);
29     printf("%d
",Bfs(r1,r2));
30     return 0;
31 }
32 inline bool Check(int x){
33     return x>=0&&x<=100000&&b[x]==0;
34 }
35 int Bfs(int r1,int r2){
36     qu.push(make_pair(r1,0));
37     b[r1]=1;
38     while(!qu.empty()){
39         pair<int,int> tmp=qu.front();
40         qu.pop();
41         if(tmp.first==r2){
42             return tmp.second;
43         }
44         int x=tmp.first+1;
45         if(Check(x)){
46             b[x]=1;
47             qu.push(make_pair(x,tmp.second+1));
48         }
49         x=tmp.first-1;
50         if(Check(x)){
51             b[x]=1;
52             qu.push(make_pair(x,tmp.second+1));
53         }
54         x=tmp.first*2;
55         if(Check(x)){
56             b[x]=1;
57             qu.push(make_pair(x,tmp.second+1));
58         }
59     }
60 }

我自己底下实验了下,把STL去掉,自己实现简易的队列,再进行暴搜,时间消耗为16ms。

代码二:【0ms】bfs剪枝(这里没有用STL):         剪枝内容:当自己的位置大于k的时候,自然不用考虑+1和*2的情况了。

 1 #include <fstream>
 2 #include <iostream>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 
 7 const int N=100005;
 8 int n,k,dis[N],queue[N];//dis:记录走到某个点的步数。 queue:因为每次队列采用去重加入,所以N是足够用了。
 9 bool b[N];//N是足够的,不需要扩展2N或者3N。打比说x先乘再减,与先减再乘,后者会更快,故不会超过N,负数是更不可能的,因为没有除法。
10 
11 int bfs();
12 
13 int main()
14 {
15     //freopen("D:\input.in","r",stdin);
16     //freopen("D:\output.out","w",stdout);
17     scanf("%d%d",&n,&k);
18     printf("%d",bfs());
19     return 0;
20 }
21 int bfs(){
22     int l,r,x;
23     l=r=0;
24     dis[n]=0;
25     queue[0]=n;
26     while(1){//队列不可能为空
27         if(queue[l]==k) return dis[k];
28         if(x=queue[l]-1,x>=0&&!b[x]){//注意边界
29             b[x]=1;
30             queue[++r]=x;
31             dis[x]=dis[queue[l]]+1;
32         }
33         if(x=queue[l]+1,queue[l]<=k&&!b[x]){//这里的queue[l]<=k为剪枝
34             b[x]=1;
35             queue[++r]=x;
36             dis[x]=dis[queue[l]]+1;
37         }
38         if(x=queue[l]<<1,queue[l]<=k&&x<N&&!b[x]){//这里的queue[l]<=k为剪枝;注意边界
39             b[x]=1;
40             queue[++r]=x;
41             dis[x]=dis[queue[l]]+1;
42         }
43         l++;
44     }
45 }
原文地址:https://www.cnblogs.com/jiu0821/p/4354571.html