题解:学而思编程 跑车与旅行
【题目来源】
学而思编程:跑车与旅行
【题目描述】
小猴终于打算驾驶自己心爱的小跑车去旅行了,为此他已经规划好了一个旅游线路,要依次参观 \(n\) 个城市(包括自己的城市)。小猴有加油强迫症,即每到一个城市,一定会将自己跑车的油箱彻底加满,否则就会浑身难受。
已知小猴的跑车每跑一公里都会消耗一升汽油,现在依次告诉你每个城市中每升汽油的价格,以及该城市与上一个到达城市的距离(单位为公里,起点城市距离自己为 \(0\))。请你帮助小猴计算到达终点城市的总加油花费(当然到最后一个城市也需要加油),但是如果小猴到不了最后的城市,请提前告诉他。
【输入】
第一行两个正整数 \(n,c\),分别表示城市的数量与小猴跑车的油箱容量。
第二行 \(n\) 个整数,表示该城市与上一个城市的距离 \(d_i\)。
第三行 \(n\) 个整数,表示该城市每升汽油的价格 \(p_i\)。
【输出】
如果小猴能够到达,请输出购买汽油总花费,否则输出他最后一个到达城市的编号。
【输入样例】
3 3
0 2 3
3 2 1
【输出样例】
16
【核心思想】
-
问题分析:小猴依次参观 \(n\) 个城市,每到一个城市必须加满油(容量 \(c\))。已知每段距离 \(d_i\) 和每升油价 \(p_i\),求到达终点的总花费;若无法到达则输出最后到达的城市编号。这是一个贪心策略 + 可行性判断问题,关键在于理解"每到一个城市加满油"意味着每段路程的油耗由当前城市的油价决定。
-
算法选择:
- 贪心累加:每段路程 \(d_i\) 的油耗在当前城市购买,花费为 \(d_i \times p_i\)
- 可行性检查:若某段距离 \(d_i > c\)(超过油箱容量),则无法到达,返回上一个城市编号
-
关键步骤:
- 初始化:读取 \(n\)(城市数)和 \(c\)(油箱容量)
- 读取数据:
- 读取距离数组 \(d[1..n]\)(\(d_1 = 0\) 为起点)
- 读取油价数组 \(p[1..n]\)
- 计算总花费:
sum = c * p[1]:在第一个城市加满油的花费- 遍历 \(i\) 从 \(2\) 到 \(n\):
- 若
d[i] > c:无法到达第 \(i\) 个城市,返回i - 1(最后到达的城市编号) - 否则:
sum += d[i] * p[i]:在第 \(i\) 个城市购买行驶 \(d_i\) 公里所需的油
- 若
- 输出
sum(能到达终点时)或i - 1(无法到达时)
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),线性遍历城市
- 空间复杂度:\(O(n)\),存储距离和油价数组
-
贪心累加的核心思想:
- 强制满油策略:每到一个城市必须加满油,意味着油箱在离开每个城市时都是满的 \(c\) 升,但实际花费只与行驶该段路程所需的油量有关
- 路段独立性:每段路程 \(d_i\) 的油耗必须在城市 \(i\) 购买(因为离开时必须满油,而到达时油箱剩余 \(c - d_i\),需加 \(d_i\) 升才能满),因此花费为 \(d_i \times p_i\)
- 可行性判定:单段距离超过油箱容量 \(c\) 时,无论如何都无法通过,提前终止
- 起点特殊处理:起点距离为 \(0\),但题目要求"到最后一个城市也需要加油",因此初始花费为 \(c \times p_1\)(在起点加满)
- 适用于"强制状态转移 + 路段费用累加"类问题,贪心策略将复杂规划简化为线性扫描
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n, c, d[100005], p[100005];
// 计算最小消耗
long long cal()
{
long long sum = c * p[1]; // 初始化总和为第一个位置的成本
for (int i = 2; i <= n; i++)
{
// 如果当前位置距离大于c,则无法到达
if (d[i] > c)
{
return i - 1; // 返回上一个位置
}
else
{
sum += d[i] * p[i]; // 累加消耗
}
}
return sum; // 返回总消耗
}
int main()
{
cin >> n >> c;
for (int i = 1; i <= n; i++)
{
cin >> d[i]; // 读取距离
}
for (int i = 1; i <= n; i++)
{
cin >> p[i]; // 读取单位消耗
}
cout << cal() << endl;
return 0;
}
【运行结果】
3 3
0 2 3
3 2 1
16
浙公网安备 33010602011771号