题意
在坐标轴上给定 \(N\) 个点,坐标依次为 \(X_1, X_2, \cdots, X_N\),你需要从原点前往 \(X_N\) 并折返,其中在第 \(1\) 个到第 \(N - 1\) 个点上有加油站,其中第 \(i\) 个加油站可以花费 \(P_i\) 购买 \(F_i\) 升汽油,汽油持有上限为 \(H\) 升,每行驶一单位距离需要花费一升汽油。在全部过程中每个加油站至多使用一次,判断是否可以完成行程并输出最小花费。
(\(1 \le N, H \le 300\))。
题解
考虑 \(\tt{DP}\),考虑将反向行驶(\(0 \leftarrow X_N\))的过程视为正向行驶(\(0 \rightarrow X_N\)),那么问题转化为了进行两次正向行驶(\(0 \rightarrow X_N\))的行程且不能使用同一个加油站的最小花费,设 \(f_{i, j, k}\) 代表行驶到第 \(i\) 个加油站,两次行程分别还持有 \(j\) 升油和 \(k\) 升油的最小花费。
转移是显然的,考虑是否加油,为哪次行程加油即可,有转移
\[\begin{aligned} f_{i + 1, j, k} &\leftarrow f_{i, j, k} \\ f_{i + 1, \min\left\{j + F_i, H\right\}, k} &\leftarrow f_{i, j, k} + P_i \\ f_{i + 1, j, \min\left\{k + F_i, H\right\}} &\leftarrow f_{i, j, k} + P_i \\ \end{aligned}\]转移是 \(\mathcal{O}(NH^2)\) 的,下面我们考虑合并答案。
我们设在第一次行程到达 \(X_N\) 后油箱的剩余油量为 \(x\),那么这也就意味着我们的第二次行程开始的起始油量只有 \(x\),但是由于在转移中我们是正向考虑的,即从 \(0\) 以满邮箱开始转移,那么我们考虑转化起始油量的限制。我们发现,若没有第一次行程的干扰,第二次行程可以视为从满油开始,若第一次行程后邮箱剩余油量为 \(x\),这也就意味着在第二次行程开始时有 \(H - x\) 升油被扣除无法使用,从正向来说就是从 \(0\) 以满油开始,到达后需剩余 \(H - x\) 升油以备扣除。那么我们有答案的表达式
\[Ans = \max\limits_{0 \le i \le H, H - i \le j \le H} f_{N, i, j} \]合并答案的复杂度是 \(\mathcal{O}(H^2)\) 的,总复杂度 \(\mathcal{O}(NH^2)\),可以通过本题。
Code
#include <bits/stdc++.h>
typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::vector<ValueMatrix> ValueCube;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
valueType N, H;
std::cin >> N >> H;
ValueVector X(N + 1, 0), F(N + 1, 0), P(N + 1, 0);
for (valueType i = 1; i <= N; ++i)
std::cin >> X[i];
for (valueType i = 1; i < N; ++i)
std::cin >> P[i] >> F[i];
constexpr valueType MAX = std::numeric_limits<valueType>::max() >> 2;
ValueCube DP(N + 1, ValueMatrix(H + 1, ValueVector(H + 1, MAX)));
DP[0][H][H] = 0;
for (valueType i = 0; i < N; ++i) {
for (valueType a = 0; a <= H; ++a) {
for (valueType b = 0; b <= H; ++b) {
valueType const dist = X[i + 1] - X[i];
if (a >= dist && b >= dist)
DP[i + 1][a - dist][b - dist] = std::min(DP[i + 1][a - dist][b - dist], DP[i][a][b]);
if (std::min(a + F[i], H) >= dist && b >= dist)
DP[i + 1][std::min(a + F[i], H) - dist][b - dist] = std::min(DP[i + 1][std::min(a + F[i], H) - dist][b - dist], DP[i][a][b] + P[i]);
if (a >= dist && std::min(b + F[i], H) >= dist)
DP[i + 1][a - dist][std::min(b + F[i], H) - dist] = std::min(DP[i + 1][a - dist][std::min(b + F[i], H) - dist], DP[i][a][b] + P[i]);
}
}
}
valueType ans = MAX;
for (valueType i = 0; i <= H; ++i)
for (valueType j = 0; j <= H; ++j)
if (j >= H - i)
ans = std::min(ans, DP[N][i][j]);
if (ans == MAX)
ans = -1;
std::cout << ans << std::endl;
return 0;
}
标签:std,dist,min,题解,valueType,行程,ABC320F,Fuel,DP
From: https://www.cnblogs.com/User-Unauthorized/p/solution-ABC320F.html