旅行家的预算 题解

2024-02-01 07:08
文章标签 题解 预算 旅行家

本文主要是介绍旅行家的预算 题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通往题目的大门

题目描述

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

  • 输入格式 第1行:5个空格分开的数据,分别表示D1 C D2 P N 第2…N+1行:每行3个空格分开的数据,分别表示油站号i, 该油站距出发点的距离Di,该油站每升汽油的价格Pi
  • 输出格式 第1行:一个数据,表示最少费用。
样例输入
275.6 11.9 27.4 2.8 2    
1 102.0 2.9    
2 220.0 2.2
样例输出
26.95

分析

这道题还是有难度的,在与一位大巨佬两个小时的语音通话后,总结出了AC这道题的方法,如下:主要是没看懂GM的题解
首先,这是一道贪心题:花最少的钱走完全程。现在,我们先来点简单的
改变一下题目,把油箱的容量改为无限,则贪心策略显而易见:

step1.

起点时一定要加油的,每升要用P元。假设中途有三个加油站,且你不想在中途加油,那么你的其实就是每一段都用的P价格的油

start--P--a[1]--P--a[2]--P--a[3]--P--end  

如果我告诉你第二个加油站每升只要 P-1 元,你还会傻傻的用上面这个方案吗?我猜不会,你可以一开始就加刚好能到第二个加油站的油,后半程就可以换成 P-1 元的油了,如下图

start--P--a[1]--P--a[2]--(P - 1)--a[3]--(P - 1)--end 

是不是赚了?我们把它一推广,就可以得到

step2.

在每个加油站加油只需加到能到达后面油价最低(且比它的油价还低)的加油站即可,若找不到这种加油站,恭喜你,可以准备直达了,中途不用换油,记:在第 i 个加油站加油用了 cost[i] 元,则有

int mi = INT_MAX, v = i;
for(int j = i + 1; j <= n; i++) {    if(a[j].p < mi && a[j].p < a[i].p) {     mi = a[j].p;      v = j    }
}
if(v == i) cost[i] = (d1 - a[i].d) / d2 * a[i].p;
else cost[i] = (a[v].d - a[i].d) / d2 * a[i].p;

不一定对哈,毕竟没认真实现过


前面的那么多都是引入,开始正题
引入已经说的很清楚了,在这道题的正解中,我们只是多加入了一个判断无解:当在一个加油站加满油还不能到达下一个加油站时,旅行失败。

还有就是因为油箱容量有上限,所有我们还需要看一下当前油箱省的油最远能到哪一个加油站,确定选最小值的距离范围
我们还考虑了一下,距离远近顺序的问题,就是一号加油站可能在二号加油站后面,所以先有一次排序。但最后发现,数据中没有这一情况。

根据思路不难得出

AC代码
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;const int MAXN = 105;
struct data { // 结构体 int i;double di, pi;
//	油站 i 离出发点的距离 Di, 每升汽油价格 Pi
} a[MAXN];
bool cmp(data x, data y) { // sort cmp 函数 return x.di < y.di;
}int main() {double d1, c, d2, p;int n;	scanf ("%lf %lf %lf %lf %d", &d1, &c, &d2, &p, &n); 
//	给定两个城市之间的距离 D1, 汽车油箱的容量 C, 每升汽油能行驶的距离 D2, 出发点每升汽油价格 P和沿途油站数 N a[0].di = 0, a[0].pi = p;for (int i = 1; i <= n; i++) {scanf ("%d %lf %lf", &a[i].i, &a[i].di, &a[i].pi);a[i].di /= d2;}a[n + 1].di = d1 / d2; n += 2;sort(a, a + n, cmp);for (int i = 1; i < n; i++) if (a[i].di - a[i - 1].di > c) { // 判断无解 printf("No solution");return 0;}double rest = 0, cost;for (int i = 0; i < n; i++) {int min_pos = i; // 价格最低的加油站的位置 double min_val = a[i].pi; // 价格最低的加油站的价格 int j, k;
//  j 剩余油量能到达的最远的加油站 
//  k j + 1 到 n - 1 中第一个比 minpos 便宜的点 for (j = i + 1; j < n && a[j].di - a[i].di <= rest; j++)if (min_val < a[j].pi)min_val = a[j].pi, min_pos = j;
//	求出价格最低的加油站的相关信息 for (k = j; k < n; k++)if (a[k].pi < min_val)break;if (k == n) // 判断能否到终点 k = n - 1;rest -= (a[min_pos].di - a[i].di); double end = (a[k].di - a[min_pos].di); 
//  rest 第一部分的路程
//  end  第二部分的路程 if (end <= c) {  // 能直接到达 Kcost += (end - rest) * a[min_pos].pi; // 加油 if (k == n - 1)break;elsei = k - 1, rest = 0; // 更新 } else {  // 否则加满油cost += (c - rest) * a[min_pos].pi;i = min_pos;  rest = c; rest -= a[i + 1].di - a[i].di;}}printf("%.2lf\n", cost);return 0;
}

这篇关于旅行家的预算 题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/666461

相关文章

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

【秋招笔试】9.07米哈游秋招改编题-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收集 100+ 套笔试题,笔试真题 会在第一时间跟新 🍄 题面描述等均已改编,如果和你笔试题看到的题面描述

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

P2858 [USACO06FEB] Treats for the Cows G/S 题解

P2858 题意 给一个数组。每天把最左或者最右的东西卖掉,第 i i i个东西,第 d a y day day天卖出的价格是 a [ i ] ∗ d a y a[i]*day a[i]∗day。 记忆化搜索 void dfs(int l,int r,int day,ll sum){if(v[l][r]>=sum)return;v[l][r]=sum;if(l>r)//这就是dp答案{

【C++题解】1272. 郭远摘苹果

欢迎关注本专栏《C++从零基础到信奥赛入门级(CSP-J)》 问题:1272. 郭远摘苹果 类型:二维数组 题目描述: 郭远有一天走到了一片苹果林,里面每颗树上都结有不同数目的苹果,郭远身上只能拿同一棵树上的苹果,他每到一棵果树前都会把自己身上的苹果扔掉并摘下他所在树上的苹果并带走(假设郭远会走过每一棵苹果树),问在郭远摘苹果的整个过程中,他身上携带的最多苹果数与最小苹果数的差是多少?

【最新华为OD机试E卷-支持在线评测】机器人活动区域(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线评测,专栏文章质量平均 94 分 最新华为OD机试目录: https://blog.

2023 CCPC(秦皇岛)现场(第二届环球杯.第 2 阶段:秦皇岛)部分题解

所有题目链接:Dashboard - The 2023 CCPC (Qinhuangdao) Onsite (The 2nd Universal Cup. Stage 9: Qinhuangdao) - Codeforces 中文题面: contest-37054-zh.pdf (codeforces.com) G. Path 链接: Problem - G - Codeforces