I - Road Optimization(cf原题)题解
[题目传送门](Problem - 1625C - Codeforces (Unofficial mirror by Menci))
题目大意:
两地之间相隔长度为 l , 其中有 n 个限速标志,最多可以删除 k 个限速标, 第 i 个限速标志表示在离起点 di 公里的距离。求从起点到终点最少需要的时间。

答案就是删除 0 ~ k 个限速标到终点的最短时间,我们并不清楚我们什么时候需要删除限速标,也不知道每次需要删除多少。
我们设置一个 a 数组用来存储每个限速标所限制的速度,d 数组用来存储每一个限速标的位置。
我们可以开一个二维数组 f [ i ] [ j ] 表示到第 i 个限速标的时候删掉了 j 个限速标的最小花费时间。这里需要注意,我们第一个限速标是不能删掉的,因为那样我们就不知道第一段距离的速度了。
在第一个限速标所需要的时间为 0 ,所以我们需要将 f [ i ] [ j ] 中 i == 1时的数据初始化为 0 。
还有就是我们用来存储每个限速标位置的数组 d 还需要去存储一下我们最后的终点,可以把终点理解成一个没有限速标的节点。
明确了数组中所对应的元素,我们再来判断一下可能会遇到的情况:
1、从上一个限速标到目前的限速标,没有删除一个限速标 / 删除了 0 个限速标(此时 j 不会改变):
f [ i ] [ j ] = f [ i - 1 ] [ j ] + ( d [ i ] - d [ i - 1 ] ) * a [ i - 1 ]; // d [ i ] - d [ i - 1 ] 表示上一个限速标的位置到目前的限速标的位置之间的距离,因为这一段的速度是上一个限速标的速度所以乘以 a [ i - 1 ]
2、从上一个限速标到目前的限速标,删除了 m 个限速标:
f [ i ] [ j ] = f [ i - 1 - m ] [ j - m ] + ( d [ i ] - d [ i - 1 - m ] ) * a [ i - 1 - m ]; // 好像删除了几个限速标就是把等号后面的变成前 n 个位置的元素。
这样看动规公式就应该是:
f [ i ] [ j ] = min ( f [ i ] [ j ] , f [ i - 1 - m ] [ j - m ] + ( d [ i ] - d [ i - 1 - m ] ) * a [ i - 1 - m ] );
** 因为第 1 个限速标不能被删除,所以在 i 个位置的时候不能删除多于 i - 1 个限速标,所以第 i 个位置能删除的最大限速标的数量应该为 min ( i - 1, k );
1 for (int i = 2; i <= n + 1; i++)//因为第 1 个限速标不能删我们可以不去考虑 2 { 3 for (int j = 0; j <= min(i - 1, k); j++) 4 { 5 for (int l = 0; l <= j; l++) 6 { 7 f[i][j] = min(f[i][j], f[i - l - 1][j - l] + (d[i] - d[i - l - 1]) * a[i - l - 1]); 8 } 9 } 10 }
最后得到的 f [ n + 1] [ 0 ~ k ] 表示到达第 n + 1 个限速标也就是到了终点的时候删除了 0 ~ k 个限速标不同情况的最小时间,所以我们需要在其中找到最小值最为最后答案。

浙公网安备 33010602011771号