华硕编程竞赛11月JAVA专场 C题太空遨游 题解

简介: 华硕编程竞赛11月JAVA专场 C题太空遨游 题解

题目链接:题目链接

题面:

小王最近得到了一艘神奇的飞船,这艘飞船只有两个脚踏板,分别是油门和刹车,飞船的原始速度 N

假设飞船的现有速度为 X,每当小王踩一下油门后,就会加速到 X * X

假设飞船的现有速度为 Y,每当小王踩一下刹车后,飞船速度就会减速到 Y - 1

这并不神奇,神奇的是飞船会出一道题,如果飞船驾驶员能正确解答这道题,就可以召唤出一条神龙,实现驾驶者的一个愿望。飞船出题的内容是求出踩脚踏板后达到预定的速度 M(0 < M < 400000)的最少次数

小王特别想有一个女朋友陪他一起遨游太空,你能帮助小王解决这个问题让他召唤出神龙满足有女朋友的愿望吗?

本次挑战需要你至少了解一些 Java 中诸如流程控制、数组、集合或队列的使用。

知识点

  • 队列/背包的基本使用
  • 广度优先搜索
  • 最佳解决方案

初始代码

import java.util.*;
public class SpaceShip{
    public static int fly(int N,int M){
       int ans = 0;
         //代码编辑区 开始   
         //代码编辑区 结束 
         return ans;
    }
    public static void main(String[] args) {
        //测试用例
        System.out.printf("从%d 到 %d 最少需要踩:%d 次,正确答案为3次.\n",2,15,fly(2, 15));
        System.out.printf("从%d 到 %d 最少需要踩:%d 次,正确答案为5次.\n",5,21,fly(5, 21));
        System.out.printf("从%d 到 %d 最少需要踩:%d 次,正确答案为13次.\n",5,30,fly(5, 30));
        System.out.printf("从%d 到 %d 最少需要踩:%d 次,正确答案为26次.\n",5,125,fly(5, 125));
        System.out.printf("从%d 到 %d 最少需要踩:%d 次,正确答案为78次.\n",5,173010,fly(5, 173010));
        System.out.printf("从%d 到 %d 最少需要踩:%d 次,正确答案为752次.\n",11,200000,fly(11, 200000));
        System.out.printf("从%d 到 %d 最少需要踩:%d 次,正确答案为2次.\n",52,50,fly(52, 50));
    }
}

样例说明

输入初始速度 N 和目标速度 M,输出踩脚踏板的最小次数。

如初始速度 N = 2,目标速度为 15,只需依次踩油门、油门、刹车即可达到,最少只需要踩 3 次。

如初始速度 N = 52,目标速度为 50,只需依次踩刹车、刹车即可达到,最少只需要踩 2 次。

刹车与油门可以只踩一种或交替进行踩踏。

题解

考察 Java 队列和 bfs 的使用,当然也可以用动态规划的思想去解决问题,对于初始速度 N 和目标速度 M,需要考虑到下列三种情况。

1 初始速度 N >= 目标速度 M,答案为 N - M,因为小王只能通过踩刹车减速。

2 初始速度 N < 目标速度 M,小王可以通过踩油门或刹车控制速度,使用广搜思想分类讨论,最终得出答案。

参考代码如下:

import java.util.*;
public class SpaceShipAns{
    // 请勿修改 fly() 的方法名和参数类型
    public static int fly(int n,int m){
        int ans = 0;
        //代码编辑区 开始
        if(n >= m) {
            return n - m;
        }
        init();
        integerList.set(n,0);
        q.add(new NodeVo(0,n));
        while(q.size() > 0) {
            NodeVo vo = q.peek();
            q.poll();
            if(integerList.get(vo.getId()) < vo.getT()) {
                continue;
            }
            if(vo.getId() <= 632) {
                int index = vo.getId() * vo.getId();
                int t = vo.getT() + 1;
                if(integerList.get(index) > t) {
                    integerList.set(index,t);
                    q.add(new NodeVo(t,index));
                }
            }
            if(vo.getId() > 2) {
                int index = vo.getId() - 1;
                int t = vo.getT() + 1;
                if(integerList.get(index) > t) {
                    integerList.set(index,t);
                    q.add(new NodeVo(t,index));
                }
            }
        }
        ans = integerList.get(m);
        //代码编辑区 结束
        return ans;
    }
    public static void main(String[] args) {
        //测试用例
        System.out.printf((Objects.equals(3,fly(2, 15)) ? "【√正确】" : "【X错误】") + "从%d 到 %d 最少需要踩:%d 次,正确答案为 3 次\n",2,15,fly(2, 15));
        System.out.printf((Objects.equals(5,fly(5, 21)) ? "【√正确】" : "【X错误】") + "从%d 到 %d 最少需要踩:%d 次,正确答案为 2 次\n",5,21,fly(5, 21));
        System.out.printf((Objects.equals(13,fly(5, 30)) ? "【√正确】" : "【X错误】") + "从%d 到 %d 最少需要踩:%d 次,正确答案为 13 次\n",5,30,fly(5, 30));
        System.out.printf((Objects.equals(26,fly(5, 125)) ? "【√正确】" : "【X错误】") + "从%d 到 %d 最少需要踩:%d 次,正确答案为 26 次\n",5,125,fly(5, 125));
        System.out.printf((Objects.equals(78,fly(5, 173010)) ? "【√正确】" : "【X错误】") + "从%d 到 %d 最少需要踩:%d 次,正确答案为 78 次\n",5,173010,fly(5, 173010));
        System.out.printf((Objects.equals(752,fly(11, 200000)) ? "【√正确】" : "【X错误】") + "从%d 到 %d 最少需要踩:%d 次,正确答案为 752 次\n",11,200000,fly(11, 200000));
        System.out.printf((Objects.equals(2,fly(52, 50)) ? "【√正确】" : "【X错误】") + "从%d 到 %d 最少需要踩:%d 次,正确答案为 2 次\n",52,50,fly(52, 50));
    }
    private static List<Integer> integerList;
    private static Queue<NodeVo> q;
    private static class NodeVo implements Comparable<NodeVo>{
        private int t;
        private int id;
        public NodeVo(int t,int id) {
            this.t = t;
            this.id = id;
        }
        public int getT() {
            return t;
        }
        public void setT(int t) {
            this.t = t;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        @Override
        public int compareTo(NodeVo other) {
            return t > other.t ? 1 : 0;
        }
    }
    private static void init() {
        integerList = new ArrayList<>();
        for(int i = 0;i < 500000; i ++) {
            integerList.add(999999999);
        }
        q = new LinkedList<>();
    }
}

总结

要 AC 本题,必须学会基于队列的 BFS (即广度优先搜索)的算法,从而通过本题。


相关文章
|
1月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
176 0
|
1月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
140 6
|
1月前
|
安全 前端开发 Java
从反射到方法句柄:深入探索Java动态编程的终极解决方案
从反射到方法句柄,Java 动态编程不断演进。方法句柄以强类型、低开销、易优化的特性,解决反射性能差、类型弱、安全性低等问题,结合 `invokedynamic` 成为支撑 Lambda 与动态语言的终极方案。
144 0
|
2月前
|
SQL Java 数据库
2025 年 Java 从零基础小白到编程高手的详细学习路线攻略
2025年Java学习路线涵盖基础语法、面向对象、数据库、JavaWeb、Spring全家桶、分布式、云原生与高并发技术,结合实战项目与源码分析,助力零基础学员系统掌握Java开发技能,从入门到精通,全面提升竞争力,顺利进阶编程高手。
528 1
|
2月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
431 100
|
2月前
|
NoSQL Java 关系型数据库
超全 Java 学习路线,帮你系统掌握编程的超详细 Java 学习路线
本文为超全Java学习路线,涵盖基础语法、面向对象编程、数据结构与算法、多线程、JVM原理、主流框架(如Spring Boot)、数据库(MySQL、Redis)及项目实战等内容,助力从零基础到企业级开发高手的进阶之路。
274 1
|
2月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
217 16
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
135 2
|
1月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
156 1
|
2月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案