[CSP-J 2023] 公路 题解

发布时间 2023-11-05 19:19:56作者: xvl

题目传送门

一道 dp 题。

好像大家写的都是贪心,这里给出一种 dp 的写法。

在 dp 之前,我们需要明确以下几个东西:

状态的表示状态转移方程边界条件答案的表示

状态的表示

\(dp_i\) 表示到达第 \(i\) 个站点所需要的最少钱数,\(w_i\) 表示在使用最少钱数到达第 \(i\) 个站点时多余的路程。

状态转移方程

\[dp_i=dp_{i-1}+\lceil\frac{v_{i-1}-w_{i-1}}{d}\rceil\times pre\_min(i-1) \]

\[w_i=\lceil\frac{v_{i-1}-w_{i-1}}{d}\rceil-v_{i-1}+w_{i-1} \]

其中 \(pre\_min(i)\) 表示前 \(i\) 个站点中最小的油价。

边界条件

\[dp_i=0 \]

\[w_i=0 \]

答案的表示

\[dp_n \]

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll n, d, ans;
ll v[100005], a[100005], dp[100005], pm[100005], w[100005];
int main() {
	// freopen("road.in", "r", stdin);
	// freopen("road.out", "w", stdout);
	ios :: sync_with_stdio(0);
	cin >> n >> d;
	pm[0] = 1e18;
	for (int i = 1; i < n; i++) cin >> v[i];
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		pm[i] = min(pm[i - 1], a[i]);
	}
	for (int i = 2; i <= n; i++) {
		dp[i] = dp[i - 1] + ceil(1.0 * (v[i - 1] - w[i - 1]) / d) * pm[i - 1];
		w[i] = ceil(1.0 * (v[i - 1] - w[i - 1]) / d) * d - (v[i - 1] - w[i - 1]);
	}
	cout << dp[n];
	return 0;
}