CF 1625C - Road Optimization


题目链接:

https://codeforces.com/problemset/problem/1625/C

题目大意:

在一条长为 \(l\) 的公路上有 \(n\) 个路标,第 \(i\) 个路标在第 \(d_i\) 米处,限速 \(a_i\),意味着在这个路标到下一个路标之间的路段最快速度是 \(a_i\) 每公里,现在你最多可以移去 \(k\) 个路标(第一个路标除外,因为移掉之后,最开始的一段路就没有限速了),求通过这条路的最短时间是多少。

思路:

看一下数据范围,500,再结合题意,可以想到通过 \(dp\) 来解。
\(dp_{i, j}\) 表示在前 \(i\) 个路标中移去 \(j\) 个路标后走完这段所花的最短的时间。

代码:

#include 
using namespace std;
const int N = 510;
int f[N][N], d[N], a[N], n, l, k;
void solve(){
	cin >> n >> l >> k;
	memset(f, 0x3f, sizeof(f));
	for (int i = 1; i <= n; i++)
		cin >> d[i];
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	d[n + 1] = l;  //最后需要到 l
	for (int i = 0; i <= k; i++)
		f[1][i] = 0;  //因为第一个路标移不了,所以初始化为 0
	for (int i = 2; i <= n + 1; i++)  //前 i 个路标
		for (int p = 0; p <= k; p++)  //移走了 p 个路标
			for (int j = 1; j < i; j++){  //从第 j 个开始移,将第 j + 1 个到第 i - 1 个都移走
				int len = i - j - 1;
				if (p >= len)
					f[i][p] = min(f[i][p], f[j][p - len] + a[j] * (d[i] - d[j]));
			}
	cout << f[n + 1][k] << "\n";
}
int main(){
	solve();
	return 0;
}
DP