贪心算法-汽车加油

news2024/11/24 19:18:30

这道题目描述了一个汽车旅行场景,需要设计一个有效的算法来决定在哪几个加油站停车加油,以便最小化加油次数。题目给出了汽车加满油后的行驶距离n公里,以及沿途若干个加油站的位置。我们需要找出一个方案,使得汽车能够完成整个旅程,同时加油次数最少。

为了更好地理解并解决问题,我们可以将其转化为数学模型和算法设计问题。首先,明确以下几个关键点:

  1. 汽车的行驶能力:汽车加满油后可以行驶n公里。
  2. 加油站分布:沿路有k个加油站,每个加油站的具体位置已知。
  3. 目标:找到一条路线,使得汽车能够完成全程,同时加油次数最少。

解决方案

我们可以使用贪心算法来解决这个问题。贪心策略的基本思想是从局部最优解入手,一步步构造全局最优解。在这里,我们的局部最优决策就是每次选择离当前位置最远的那个加油站作为下一个加油地点。

步骤如下:

  1. 初始化变量

    • 当前位置设为起点。
    • 加油次数计数器置零。
  2. 迭代过程

    • 遍历所有的加油站,寻找离当前位置最远但又不会超过汽车行驶范围的加油站。
    • 如果找到了这样的加油站,就在那里加油,并更新当前位置。
    • 同时,加油次数计数器加一。
  3. 结束条件

    • 如果没有找到合适的加油站,说明当前油量不足以达到任何一个加油站,返回“No Solution”。
    • 如果已经到达终点,停止搜索。

实现细节

  • 数据结构:可以用一个列表或数组来保存加油站的位置。
  • 算法流程:按照上述步骤编写程序逻辑,需要注意的是,在每次选择加油站之后,都要检查是否还能到达下一个加油站,否则就需要再次加油。

注意事项

  • 确保加油站的位置是按顺序排列的,这样可以简化查找过程。
  • 在实际编码过程中,要注意边界条件的处理,避免出现越界错误。

通过这种方法,我们可以有效地解决这个问题,找到最少加油次数的方案。如果在某一步发现无法前进,那么就表明没有可行的解决方案,此时应返回“No Solution”。

假设我们有一个int[] gasStations数组,它包含了从起点到终点所有加油站的位置(公里数),并且汽车加满油后能行驶的最大距离为int maxDistance。我们将从起点开始尝试到达终点,途中尽可能少地加油。

import java.util.Arrays;

public class MinimumRefuelStops {
    public static void main(String[] args) {
        int maxDistance = 10; // 汽车加满油后能行驶的最大距离
        int[] gasStations = {2, 5, 7, 10}; // 加油站位置,单位为公里
        int destination = 10; // 目的地的位置
        
        System.out.println(minimumRefuelStops(maxDistance, gasStations, destination));
    }

    /**
     * 计算最少加油次数。
     *
     * @param maxDistance 汽车加满油后能行驶的最大距离
     * @param gasStations 加油站位置数组
     * @param destination 目的地的位置
     * @return 最少加油次数,若无法到达目的地则返回"No Solution"
     */
    public static String minimumRefuelStops(int maxDistance, int[] gasStations, int destination) {
        int currentPosition = 0; // 当前位置
        int refuelCount = 0; // 加油次数
        int nextStationIndex = 0; // 下一个加油站的索引

        while (currentPosition < destination) {
            // 找到最远可以到达的加油站
            while (nextStationIndex < gasStations.length && gasStations[nextStationIndex] <= currentPosition + maxDistance) {
                nextStationIndex++;
            }

            // 如果当前位置已经超过了最后一个加油站,但仍未到达目的地
            if (nextStationIndex == gasStations.length && currentPosition + maxDistance < destination) {
                return "No Solution";
            }

            // 如果当前位置已经可以到达或超过目的地
            if (currentPosition + maxDistance >= destination) {
                break;
            }

            // 如果有可用的加油站,选择最远的一个加油
            if (nextStationIndex > 0) {
                currentPosition = gasStations[nextStationIndex - 1];
                refuelCount++;
            } else {
                // 没有可以到达的加油站
                return "No Solution";
            }
        }

        return String.valueOf(refuelCount);
    }
}

这段代码中,我们定义了一个minimumRefuelStops方法来计算最少加油次数。该方法首先初始化当前位置和加油次数,然后在一个循环中不断寻找最远可以到达的下一个加油站,直到汽车能够到达目的地或者确定无法到达目的地为止。

注意,这个例子假设了gasStations数组中的元素已经按照从小到大的顺序排序,这是合理的,因为加油站的位置应该是沿着路径递增的。如果实际情况不是这样,您可能需要先对gasStations数组进行排序。

在每次决定是否加油时,贪心算法会选择在当前油量不足以到达下一个加油站或目的地时才进行加油。这种选择保证了每次加油都是必要的,避免了不必要的加油操作,从而减少了总的加油次数。

package tanxin;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class CarsStop {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int n = scanner.nextInt(); // 输入加满油可行驶的公里数
        int k = scanner.nextInt(); // 输入加油站数量

        int[] distances = new int[k + 1]; // 定义数组存储相邻加油站之间的距离,最后一个元素是最后一个加油站到目的地的距离
        for (int i = 0; i < k; i++) {
            distances[i] = scanner.nextInt(); // 读取相邻加油站之间的距离
        }
        distances[k] = scanner.nextInt(); // 最后一个加油站到目的地的距离

        int m = 0; // 初始化加油次数为0
        int t = n; // 汽车开始可行驶的公里数
        List<Integer> stations = new ArrayList<>(); // 存储加油的加油站编号

        for (int i = 0; i <= k; i++) { // 包括最后一个加油站到目的地的距离
            if (distances[i] > n) { // 如果某段距离大于汽车的最大行驶距离,输出无解并退出程序
                System.out.println("No Solution");
                return;
            }
            if (t < distances[i]) { // 如果当前剩余油量不足以到达下一个地点,则需要加油
                
                t = n; // 汽车加一次油,汽车能行驶的距离变为n
                m++; // 加油次数+1
                stations.add(i - 1); // 记录加油的加油站编号,注意这里是i-1因为是在到达i站之前加油
            }
            t -= distances[i]; // 减去已行驶的距离
        }

        System.out.println("加油次数为:" + m); // 输出加油次数
        if (!stations.isEmpty()) {
            System.out.print("加油地点:");
            for (Integer station : stations) {
                System.out.print("第" + (station + 1) + "个加油站, ");
            }
            System.out.println(); // 换行
        }
    }
}
  1. 输入读取

    • 首先,程序通过 Scanner 类读取用户输入的数据。包括汽车加满油后可以行驶的最大距离 n 和加油站的数量 k
    • 然后,程序读取每个加油站之间的距离(存入 distances 数组),以及最后一个加油站到目的地的距离。
  2. 初始化变量

    • m 变量用于记录加油次数,初始值为0。
    • t 变量代表汽车当前还剩多少公里可以行驶,初始值为 n,即汽车加满油后的最大行驶距离。
    • stations 列表用来存储每次加油时所在的加油站编号。
  3. 核心逻辑

    • 使用一个循环遍历所有加油站的距离数据,包括从最后一个加油站到目的地的距离。
    • 对于每一个距离 distances[i],首先检查该距离是否超过了汽车的最大行驶距离 n,如果是,则输出“无解”并结束程序。
    • 接着,判断当前剩余油量 t 是否足够行驶至下一个加油站或目的地。如果不够,则需要在当前加油站加油,并更新相关变量:
      • 将 t 重置为 n,表示汽车加满油后能行驶的最大距离。
      • 增加加油次数 m
      • 记录加油的加油站编号 i - 1 到 stations 列表中(注意这里是因为加油是在到达下一个加油站之前完成的)。
    • 更新 t,减去已经行驶过的距离 distances[i]
  4. 输出结果

    • 循环结束后,输出总的加油次数 m
    • 如果有加油记录,还会输出具体的加油地点。

示例运行

假设输入如下:

7 7
1 2 3 4 5 1 6 1

这表示汽车加满油后可以行驶的最大距离为7公里,总共有7个加油站,各加油站间的距离分别为1, 2, 3, 4, 5, 1公里,最后一个加油站到目的地的距离为6公里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2238719.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【动手学电机驱动】STM32-FOC(6)基于 IHM03 的无感方波控制

STM32-FOC&#xff08;1&#xff09;STM32 电机控制的软件开发环境 STM32-FOC&#xff08;2&#xff09;STM32 导入和创建项目 STM32-FOC&#xff08;3&#xff09;STM32 三路互补 PWM 输出 STM32-FOC&#xff08;4&#xff09;IHM03 电机控制套件介绍 STM32-FOC&#xff08;5&…

CNN实现地铁短时客流预测

项目源码获取方式见文章末尾&#xff01; 600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…

SDL打开YUV视频

文章目录 问题1&#xff1a;如何控制帧率&#xff1f;问题2&#xff1a;如何触发退出事件&#xff1f;问题3&#xff1a;如何实时调整视频窗口的大小问题4&#xff1a;YUV如何一次读取一帧的数据&#xff1f; 问题1&#xff1a;如何控制帧率&#xff1f; 单独用一个子线程给主线…

Linux 系统结构

Linux系统一般有4个主要部分&#xff1a;内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构&#xff0c;它们使得用户可以运行程序、管理文件并使用系统。 1. linux内核 内核是操作系统的核心&#xff0c;具有很多最基本功能&#xff0c;它…

使用vscode 连接linux进行开发

1. 在Vscode中安装扩展功能remote ssh 2. 打开命令窗口 3. 在弹出的命令窗口输入ssh&#xff0c;并从弹出的提示中选择 Add New SSH Host 4. 在弹出的输入窗口中输入类似下面形式的 连接地址&#xff1a; 5. 输入回车后出现下面的对话框&#xff0c;这个对话框是说你要用哪个…

【C++】 C++游戏设计---五子棋小游戏

1. 游戏介绍 一个简单的 C 五子棋小游戏 1.1 游戏规则&#xff1a; 双人轮流输入下入点坐标横竖撇捺先成五子连线者胜同一坐标点不允许重复输入 1.2 初始化与游戏界面 初始化界面 X 输入坐标后 O 输入坐标后 X 先达到胜出条件 2. 源代码 #include <iostream> #i…

计算机新手练级攻略——如何搜索问题

目录 计算机学生新手练级攻略——如何搜索问题1.明确搜索意图2.使用精确关键词3.使用专业引擎搜索4.利用好技术社区1. Stack Overflow2. GitHub3. IEEE Xplore4. DBLP 5.使用代码搜索工具1. GitHub 代码搜索2. Stack Overflow 代码搜索3. Papers with Code4. IEEE Xplore 6.查阅…

【MySQL】MySQL基础知识复习(下)

前言 上一篇博客介绍了MySQL的库操作&#xff0c;表操作以及CRUD。 【MySQL】MySQL基础知识复习&#xff08;上&#xff09;-CSDN博客 本篇将进一步介绍CRUD操作&#xff0c;尤其是查找操作 目录 一.数据库约束 1.约束类型 1.1NULL约束 1.2UNIQUE&#xff1a;唯一约束 …

从0开始学docker (每日更新 24-11-6)

限制容器运行的资源 限制容器的内存使用 容器的内存包括两部分&#xff1a;物理内存和交换空间&#xff08;swap&#xff09; 用户内存限制 -m,--memory&#xff1a;容器可用的最大内存&#xff0c;该值最低为4MB --memory-swap&#xff1a;允许容器置入磁盘交换空间的内存…

C++初阶——vector

一、什么是vector vector是表示可变大小的数组的序列容器&#xff0c;就像数组一样&#xff0c;vector也采用连续空间来存储元素。也就是说它的访问和数组一样高效&#xff0c;但是它的大小是动态可变的&#xff0c;并且它的大小会被容器自动处理。 二、vector的构造 常用的构…

GIT的基本使用与进阶

GIT的简单入门 一.什么是git&#xff1f; Git 是一个开源的分布式版本控制系统&#xff0c;用于跟踪文件更改、管理代码版本以及协作开发。它主要由 Linus Torvalds 于 2005 年创建&#xff0c;最初是为 Linux 内核开发而设计的。如今&#xff0c;Git 已经成为现代软件开发中…

CulturalBench :一个旨在评估大型语言模型在全球不同文化背景下知识掌握情况的基准测试数据集

2024-10-04&#xff0c;为了提升大型语言模型在不同文化背景下的实用性&#xff0c;华盛顿大学、艾伦人工智能研究所等机构联合创建了CulturalBench。这个数据集包含1,227个由人类编写和验证的问题&#xff0c;覆盖了包括被边缘化地区在内的45个全球区域。CulturalBench的推出&…

C语言中,“extern”关键字的含义与用法

在C语言中&#xff0c;extern 关键字用于声明一个已经在其他地方定义的变量或函数。它的主要作用是告诉编译器&#xff0c;某个变量或函数是在当前文件之外定义的&#xff0c;编译器应该在链接阶段找到这个变量或函数的实际定义。以下是 extern 的一些常见用途和用法&#xff1…

「Mac玩转仓颉内测版1」入门篇1 - Cangjie环境的搭建

本篇详细介绍在Mac系统上快速搭建Cangjie开发环境的步骤&#xff0c;涵盖VSCode的下载与安装、Cangjie插件的离线安装、工具链的配置及验证。通过这些步骤&#xff0c;确保开发环境配置完成&#xff0c;为Cangjie项目开发提供稳定的基础支持。 关键词 Cangjie开发环境搭建VSC…

Kubernetes网络揭秘:从DNS到核心概念,一站式综述

文章目录 一.overlay vs underlayL2 underlayL3 underlay 二、calico vs flannel2.1 calico架构2.2 flannel架构 三、iptables四、Vxlan五、kubernetes网络架构综述六、DNS七、Kubernetes域名解析策略 一.overlay vs underlay overlay网络是在传统网络上虚拟出一个虚拟网络&am…

飞凌嵌入式FET527N-C核心板现已适配Android 13

飞凌嵌入式FET527N-C核心板现已成功适配Android13&#xff0c;新系统的支持能够为用户提供更优质的使用体验。那么&#xff0c;运行Android13系统的FET527N-C核心板具有哪些突出的优势呢&#xff1f; 1、性能与兼容性提升 飞凌嵌入式FET527N-C核心板搭载了全志T527系列高性能处…

破解仓库管理难题!库存管理流程详解

随着市场竞争加剧和客户需求不断提升&#xff0c;企业的仓库管理在日益复杂的供应链环境中面临诸多挑战。许多企业在仓库管理上仍停留在传统手工操作或基础的数字化管理阶段&#xff0c;这种方式容易导致库存信息不准确、管理效率低下、数据滞后等问题。 企业现状 当前&#…

电缆管道高效智能化管理:智能电缆管道可视化机器人

电缆管道高效智能化管理&#xff1a;智能电缆管道可视化机器人 电缆管道作为城市“生命线”的重要组成部分&#xff0c;其安全性和可靠性日益受到重视。然而&#xff0c;传统的人工巡检方式存在诸多不足&#xff0c;如巡检效率低下、安全隐患大、难以发现隐蔽故障等。 很多电力…

tomcat启动失败和缓存清理办法

tomcat只在学校接触过并且是在window xp和win7的电脑上配置过&#xff08;中途升级过电脑系统&#xff09;&#xff0c;只记得在windows系统上可以将其设置成服务管理。但我已毕业10多年了&#xff0c;学的知识早就不知道丢哪里了。这次为了修改一个07&#xff0c;08年的项目&a…

RDD 算子全面解析:从基础到进阶与面试要点

Spark 的介绍与搭建&#xff1a;从理论到实践_spark环境搭建-CSDN博客 Spark 的Standalone集群环境安装与测试-CSDN博客 PySpark 本地开发环境搭建与实践-CSDN博客 Spark 程序开发与提交&#xff1a;本地与集群模式全解析-CSDN博客 Spark on YARN&#xff1a;Spark集群模式…