旅行家的预算[贪心]

news/2024/7/3 0:36:11

题目

Problem description

一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时油箱是空的)。给定两个城市之间的距离D1、汽车油箱的容量C(以升为单位).每升汽油能行驶的距离D2、出发点每升汽油价格P和沿途油站数N(N可以为零),油站i离出发点的距Di、每升汽油价格 Pi( i=l,2,...N)。计算结果四舍五入至小数点后两位。如果无法到达目的地,则输出“-1”。

Input

输入数据的第一行是四个实数;
D1 C D2 P分别表示两个城市之间的距离,汽车油箱的容量,每升汽油能行驶的距离,出发点每升汽油格;
第二行是一个整数N,沿途的油站数。
第三行到第N+2,每一行是一个油站的基本信息描述,包括该油站离出发点的距离,该油站每升汽油的格。 Output
输出到达目的城市的最小费用(四舍五入到两位小数),若不能到达目的城市则输出 -1

Sample Input 
275.6  11.9   27.4  2.8
2
102.0  2.9
220.0   2.2 Sample Output 
26.95Problem Source 
// 测试用例
275.6  11.9   17.4  2.8
2
102.0  2.9
220.0   2.21
42.54//
275.6  11.9   10.4  2.8
3 
102.0  2.1
160.2  2.3
220.0  2.2
62.99

分析:

哨兵单元往往能够简化逻辑,减少判断和边界处理。在这道题中尤为明显。
我们把出发点当做距离为0,油价为p和普通油站放在一起;把目的地当做距离为s,油价为-1的油站跟普通油站放在一起。这样就得到了一个包含n+2个油站的数组。问题变得更加清楚简洁。

假如当前在第i个油站,那么唯一需要考虑的就是在这个油站需要加多少油。
这就需要考虑后面的油站:我只需要尽量保证我的油能够到达下一个比较便宜的油站即可。如果无法到达下一个便宜油站,那么我就需要加满油;如果我加满油依然无法到达下一个便宜的油站,那么我仍然需要加满油。

而经过“哨兵单元”处理,我们把目的地当做一个距离为s,油价为-1的油站放进了油站数组里面,所以我们一定能够找到下一个便宜的油站。这样就简化了逻辑。

如果潦草地写,这道题复杂度为$O(N^2)$,利用单调栈从左往右初始化每个元素的右面较小值,可以实现O(N)复杂度。

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;public class Main {
class Point {double dis, price;Point(double dis, double price) {this.dis = dis;this.price = price;}
}Main() {Scanner cin = new Scanner(System.in);double s = cin.nextDouble(), c = cin.nextDouble(), d = cin.nextDouble(), p = cin.nextDouble();int n = cin.nextInt();Point[] a = new Point[n + 2];for (int i = 0; i < n; i++) a[i] = new Point(cin.nextDouble(), cin.nextDouble());a[n] = new Point(0, p);a[n + 1] = new Point(s, -1);//终点的油是免费的Arrays.sort(a, Comparator.comparing(x -> x.dis));double money = 0, oil = 0, lastPos = 0;for (int i = 0; i < a.length; i++) {oil -= (a[i].dis - lastPos) / d;//剩余的油量if (oil < 0) {money = -1;break;}if (a[i].price < 0) break;int j = i + 1;for (; j < a.length; j++) {if (a[j].price < a[i].price) break;}double dis = a[j].dis - a[i].dis;double need = dis / d;//到达下一站需要的油量need = Math.min(c, need);double add = need - oil;//现在需要加的油量if (add > 0) {money += add * a[i].price;oil += add;}lastPos = a[i].dis;}if (money == -1) System.out.println(-1);else {long x = Math.round(money * 100);System.out.println(x / 100 + "." + x % 100);}
}public static void main(String[] args) {new Main();
}
}

http://lihuaxi.xjx100.cn/news/236255.html

相关文章

CODING 最佳实践:快课网研发效能提升之路

快课企业移动学习平台是上海快微网络科技有限公司自主研发的企业级 SaaS 平台&#xff0c;提供移动学习、考试练习、培训管理、知识分享、统计分析等学习和培训功能&#xff0c;为员工、经销商及客户等全价值链合作伙伴提供全面的知识服务。本文将详细介绍快课网的研发团队是如…

织梦html引入html代码,织梦标签引入共html.doc

织梦标签引入共html1.无法在这个位置找到: {dede:include filename"织梦模板include插入非模板目录文件出现“无法在这个位置找到”错误的解决办法以下是dede V55_UTF8查dede include标签手册(3) include 引入一个文件&#xff0c;形式为&#xff1a;{dede:include file文…

101种设计模式

https://sourcemaking.com/design-patterns-and-tips

htcd816+android密码,HTC Desire 816刷机解锁教程

一、解锁前的准备&#xff1a;1.解锁将会丢失所有数据&#xff0c;请先做好备份&#xff0c;如电话本、短信、照片、应用程序。2.下载并安装驱动程序HTC Driver。3.注册HTC Dev帐号&#xff0c;为提交解锁码做好准备。4.下载并解压 “Desire 816 解锁工具”&#xff1a;5.手机关…

学习 JavaScript (四)核心概念:操作符

JavaScript 的核心概念主要由语法、变量、数据类型、操作符、语句、函数组成&#xff0c;前面三个上一篇文章已经讲解完了。后面三个内容超级多&#xff0c;这篇文章主要讲解的是操作符。 操作符 什么叫做操作符&#xff1f; 这是一种工具&#xff0c;帮助我们操作字符串、数字…

android设备未指定怎么办,APKpath未指定为模块“示例 – 示例”

退出Android工作室 。 用pipe理员权限启动它。这解决了Windows 7中的 Android Studio v0.1的问题。我有同样的问题&#xff0c;我没有select 2个文件&#xff0c;然后收到错误"ERROR: APK path is not specified for module"我刚刚重新启动Android Studio并重新打开该…

Java多线程编程实战:模拟大量数据同步

背景 最近对于 Java 多线程做了一段时间的学习&#xff0c;笔者一直认为&#xff0c;学习东西就是要应用到实际的业务需求中的。否则要么无法深入理解&#xff0c;要么硬生生地套用技术只是达到炫技的效果。 不过笔者仍旧认为自己对于多线程掌握不够熟练&#xff0c;不敢轻易应…

django html数据库连接,Django数据库连接的问题

多线程运行项目。有N个工作线程从DB中获取jobs&#xff0c;并把结果写回DB。项目运行一段时间后&#xff0c;发现数据库连接耗尽了&#xff0c;幸好内存大&#xff0c;然后一直往上调&#xff0c;最后连接数都上8000多。耗尽连接数的时候&#xff0c;postgresql会出现类似这样的…