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\n",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 }

你可能感兴趣的:(catch)