Catch That Cow——3278

题目

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?
翻译:奶农要抓牛,他们在一条线上,一次可以往左或者往右移动一步,或者直接心灵传送到2倍当前位置。问最少需要几步能抓到奶牛?

Input

Line 1: Two space-separated integers: N and K
输入N(奶农)位置,K(奶牛位置)

Output

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
输出最小抓到奶牛的步数。

思路

广搜,广搜搜到了就是最优值,而且复杂度还小。
搜索题目,最主要是确定搜索边界和如何扩展节点。

当奶农位置大于奶牛的时候,我们只有一种往左移动的情况,就是一个位置一个位置慢慢走,所以,可以判断一下,当这种情况,直接输出即可,不用再去搜索了。

当奶牛在奶农右边的时候,我们可以利用三种情况不断扩展可能到达的节点进入队列之中。当N<K时,所以,我们需要确定边界。至于边界是什么?

右边界,因为当我们超出了奶牛的位置的时候,只能一个格子一个格子往左走了,所以,最多也就只能到(K+(K-N))的位置,因为从那里,我们直接一个一个往左走,那还不如直接我们从一开始就往右走;

左边界,最多也就只能到(N-(K-N)),我们也是一个道理。然后进行广搜,找到了就可以了!

代码

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

class Point
{
    int x;//坐标
    int step;//步数
}

public class  Main{
    static int N;//起点
    static int K;//终点
    static Queue<Point> queue=new LinkedList();
    static int visited[]=new int[200009]; //标记数组

    public static void main(String[] args) {
        Scanner reader=new Scanner(System.in);
            N=reader.nextInt();//接收起点
            K=reader.nextInt();//接收终点

            if (K<=N) {
                System.out.println(N-K);
                return;
            }
            queue.clear();//清空队列
            int end=K+K-N;

            for (int i=0;i<=end;++i)
                visited[i]=0;

            //队头节点入队
            Point temp=new Point();
            temp.x=N;
            temp.step=0;
            queue.offer(temp);
            visited[N]=1;
            while (!queue.isEmpty())
            {
                int front_x=queue.peek().x;
                int front_step=queue.peek().step;
                if (front_x==K) {
                    System.out.println(front_step);
                    break;
                }
                //扩张右边点
                if (front_x+1>=0 && front_x+1<=end && visited[front_x+1]==0)
                {
                    Point b=new Point();
                    b.x=front_x+1;
                    b.step=front_step+1;

                    queue.offer(b);
                    visited[front_x+1]=1;
                }
                //扩展两倍节点
                if (front_x*2>=0 && front_x*2<=end && visited[front_x*2]==0)
                {
                    Point c=new Point();
                    c.step=front_step+1;
                    c.x=front_x*2;
                    queue.offer(c);
                    visited[front_x*2]=1;
                }
                //扩张左边点
                if (front_x-1>=0 && front_x-1<=end && visited[front_x-1]==0)
                {
                    Point a=new Point();
                    a.step=front_step+1;
                    a.x=front_x-1;
                    queue.offer(a);
                    visited[front_x-1]=1;
                }
                queue.poll();//弹出队首
            }
    }
}

结果

ac了,但是这道题踩了不少坑,也算有收获的。

对于,深搜和广搜,不仅仅只会做那些迷宫的题目了,只要能找到边界和往下搜索的条件就可以进行搜索!

对于数组而言,题目要求是10w,那么标记数组一定要开20w,因为有个两倍的,就是 K和 N同时是10w,数组这样子也不会越界!
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值