问题描述

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

输入格式

  第一行为4个实数D1、C、D2、P与一个非负整数N;

  接下来N行,每行两个实数Di、Pi。

输出格式

  如果可以到达目的地,输出一个实数(四舍五入至小数点后两位),表示最小费用;否则输出“No Solution”(不含引号)。

样例输入

275.6 11.9 27.4 2.8 2

102.0 2.9

220.0 2.2

样例输出

26.95

思路:还是要先吐槽一下,好多网上的教程都是错的啊,什么直接走到头然后不能走了在当前的加油站加上油到下一个加油站就行,感觉根本就是欺负蓝桥杯的数据规模。事实上这个题完全想清楚还是不太容易的。下面讲题。

我们先分析数据知道,加油站有位置,油价。然后车的油箱有容量,猛一想并不是直接就能相通如何找到停留点的,具体看下面的分析。

我们先分析一下需要什么变量,车有可能有油,有可能没油,所以需要一个变量记录油箱剩下多少油。然后我们想一下,如果当前在第i个加油站,而只有行驶到第i+k个加油站油价更便宜,那么肯定停下在i+k点加油比较合算,那么我们肯定就要记录每次停下的位置(因为后面分析是贪心,贪心的思想就是将一个线段分成几份走完,局部最优求整体最优。)

首先确定如何判断无法到达目的地的情况:我们知道 车辆不加油的最大行驶距离== (油箱容量)c * (每升油的行驶距离)d2 那么当存在相邻两个加油站的间距比车辆不加油的最大行驶距离还大的话,到目标点是不可能完成的。

然后我们分析一下车辆的行驶情况

1.假如当前点为i,在车辆不加油的最大行驶距离内存在第i+k处油价更低

(1)油箱内剩余的油可以到达该位置

这种情况我们直接用剩下的油跑到i+k点就可以了,不花钱肯定是最节省的!

(2)油箱内剩余的油不够到达该位置

在这种情况是肯定是要加油的,而且无疑我们肯定是加当前点i的油是最划算的。那么应该加多少呢?加上油刚刚好到达i+k点是最好的! 因为i+k的油比i的油便宜,没必要在i位置多加油,如果后面需要在i+k加更划算。

2.假如当前点为i,在车辆不加油的最大行驶距离内不存在第i+k处油价更低

这个时候怎么办!我们加满油去跑一定划算,因为以i为起点在车辆不加油的最大行驶距离内 行驶一定找不到价格更低的加油站,我们一定是在价格相对最低的地方加油比较好。具体加油的多少还要看下一步能不能到更便宜的加油站,如果有参考1行进,如果没有继续参考2行进。

然后我的代码有一些特点,首先变量名比较长啊…海涵…然后是用结构体记录的第0位置是起点,第n+1位置是终点,终点的油价变量我设为0,可以理解为最便宜的,所以程序一定回到n+1点去!为什么说这个在程序实现的过程中就能体会到了。

我的具体代码基本上都注释了,如果有不明白的欢迎提问!

这篇文章原c++编写的,我也是小白

原文在:

https://blog.csdn.net/qq_35078631/article/details/62897099

import java.util.Scanner;

public class Main{
static double a []; //位置
static double b [];//油价
static double last_oil; //油箱剩余空间
static double run_c; //剩余油料可以行走的最大距离
static int best_pos; //形成内最小油料价格的位置
static double full_run; //邮箱在满了的情况下可以跑多远
static double use=0;
static double d1,c,d2,p;
static int n;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
d1=sc.nextDouble();
c=sc.nextDouble();
d2=sc.nextDouble();
p=sc.nextDouble();
n=sc.nextInt();
a=new double [n+2];
b=new double [n+2];
for (int i = 1; i <=n; i++) {
a[i]=sc.nextDouble();
b[i]=sc.nextDouble();
}
a[0]=0;a[n+1]=d1;
b[0]=p;b[n+1]=0;
last_oil=0; //初始化邮箱剩余油量
best_pos=0; //初始化初始位置
full_run=c*d2; for(int i=0;i<=n;i++){ //验证是否可达
if(a[i+1]-a[i]>full_run){
System.out.println("No Solution");
}
}
run(); System.out.println((use)); }
public static void run(){ if(best_pos==n+1) return ;
int flag=0; //标记在最大行程内有没有找到费用更少的收费站
run_c=last_oil*d2;
for(int i=best_pos+1;i<=n+1;i++){
if(a[i]-a[best_pos]<=full_run){ //必须在full_run范围之内
if(b[i]<=b[best_pos]){ //如果是更优的选择
flag=1; //标记
if(run_c>=a[i]-a[best_pos]){ //如果剩下的油已经够跑了
last_oil=(a[i]-a[best_pos])/d2; //剩余油量更新
}
else{ //如果剩下的油不够跑
last_oil=0; //要恰好跑到价格更低的加油站
use+=(a[i]-a[best_pos]-run_c)/d2*b[best_pos];
}
best_pos=i; //更新最优节点
break;
}
}
} if(flag==0){ //没有匹配到最优解
int better_pos=best_pos+1;
for(int i=best_pos+1;i<=n+1;i++){ //一定是不可能到n+1的,因为n+1的在上面是一定可以匹配的!因为a[n+1].price是0!
if(a[i]-a[best_pos]<=full_run){
if(b[i]<b[better_pos]){
better_pos=i;
}
}
}
//找到了更优值
use+=(c-last_oil)*b[best_pos]; //一定是加满油最好了!因为在满油的行车范围内都到不了最优的,所以一定要加满油
last_oil=c-(a[better_pos]-a[best_pos])/d2; //先更新到达better_pos位置剩下的油料
best_pos=better_pos;
}
run(); }
}

Java实现蓝桥杯 算法训练 ALGO-15 旅行家的预算的更多相关文章

  1. Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)

    试题 算法训练 猴子吃包子 问题描述 从前,有一只吃包子很厉害的猴子,它可以吃无数个包子,但是,它吃不同的包子速度也不同:肉包每秒钟吃x个:韭菜包每秒钟吃y个:没有馅的包子每秒钟吃z个:现在有x1个肉 ...

  2. Java实现蓝桥杯 算法训练 大等于n的最小完全平方数

    试题 算法训练 大等于n的最小完全平方数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输出大等于n的最小的完全平方数. 若一个数能表示成某个自然数的平方的形式,则称这个数为完全平 ...

  3. Java实现 蓝桥杯 算法训练 画图(暴力)

    试题 算法训练 画图 问题描述 在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色. 下图给出了一个画了两个矩 ...

  4. Java实现 蓝桥杯 算法训练 Lift and Throw

    试题 算法训练 Lift and Throw 问题描述 给定一条标有整点(1, 2, 3, -)的射线. 定义两个点之间的距离为其下标之差的绝对值. Laharl, Etna, Flonne一开始在这 ...

  5. Java实现 蓝桥杯 算法训练 Airport Configuration

    试题 算法训练 Airport Configuration 问题描述 ACM机场是一个本地机场,对于大多数人来说,机场不是他们的终点或起点,而是中转站.机场有一个规划图.到达的大门在机场的北边(相当于 ...

  6. Java实现 蓝桥杯 算法训练 Rotatable Number(暴力)

    试题 算法训练 Rotatable Number 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 Bike是个十分喜欢数学的聪明孩子.他发明了"可旋转数",其灵感 ...

  7. Java实现 蓝桥杯 算法训练 最大的算式

    算法训练 最大的算式 时间限制:1.0s 内存限制:256.0MB 问题描述 题目很简单,给出N个数字,不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量大.因为 ...

  8. Java实现蓝桥杯 算法训练 Professor Monotonic's Network

    试题 算法训练 Professor Monotonic's Network 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 无聊的教授最近在做一项关于比较网络的实验.一个比较网络由若 ...

  9. Java实现 蓝桥杯 算法训练 1的个数

    试题 算法训练 1的个数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输入正整数n,判断从1到n之中,数字1一共要出现几次.例如1123这个数,则出现了两次1.例如15,那么从1 ...

  10. java实现 蓝桥杯 算法训练 Password Suspects

    问题描述 在年轻的时候,我们故事中的英雄--国王 Copa--他的私人数据并不是完全安全地隐蔽.对他来说是,这不可接受的.因此,他发明了一种密码,好记又难以破解.后来,他才知道这种密码是一个长度为奇数 ...

随机推荐

  1. 【Hadoop离线基础总结】关键路径转化率分析(漏斗模型)

    关键路径转化 需求 在一条指定的业务流程中,各个步骤的完成人数及相对上一个步骤的百分比 模型设计 定义好业务流程中的页面标识 Step1. /item Step2. /category Step3. ...

  2. Tomcat服务器的下载与安装,修改端口号

    安装及简单配置Tomcat服务器: 1.登录www.apache.org 网站,之后点击Projects , 点击Project List,找到Tomcat. 2.点击Tomcat之后,之后进入Tom ...

  3. 设计模式之GOF23模板模式

    模板模式template method 场景:具有具体流程,但具体某一步的业务不同 到银行办理业务:排队取号,办理业务,给员工打分 请客吃饭:等待,点单,吃饭,结账 模板方法模式介绍:模板方法是编程常 ...

  4. 【漫画】互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock

    ReentrantLock完美实现了互斥,完美解决了并发问题.但是却意外发现它对于读多写少的场景效率实在不行.此时ReentrantReadWriteLock来救场了!一种适用于读多写少场景的锁,可以 ...

  5. springBoot第二种配置文件yaml书写方式及读取数据、整合myBatis和整合junit

    一.yaml文件格式:key-value形式:可以表示对象 集合 1.语法:key:value 冒号后面必须跟一个空格再写value值 key1: key2: key3:value 2.属性取值:a. ...

  6. linux-设置代理和取消代理

    设置代理: export http_proxy="http://proxy-XXXXX" export https_proxy="https://proxy-XXXXX: ...

  7. Spring初学笔记(一):Spring IOC的理解

    关于依赖注入.控制反转 Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的 ...

  8. chrome "items hidden by filters"

    今天更新chrome 后遇到console不能显示errors的问题,折腾一番后发现在console的Default levels中选择Default即可.

  9. mysql小白系列_02 mysql源码安装标准化

    问题: 1.为什么数据目录和日志目录需要分开? 2.如何标准化配置多实例?(例如:一台物理主机上部署3306与3307两个实例) 3.详细描述MySQL编译安装的过程(截图安装步骤) 1.为什么数据目 ...

  10. 判断数组的方法/判断JS数据类型的四种方法

    参考文: 以下 3 个判断数组的方法,请分别介绍它们之间的区别和优劣Object.prototype.toString.call() . instanceof 以及 Array.isArray() h ...