题解:P14535 [OII 2025] 木材运输 / Trasporto tronchi
思路还是比较好想的,简化一下问题:可以认为在 \(x\) 轴正半轴上排列着 \(N\) 个点,从原点至正方向坐标依次为 $a_n,a_{n-1},a_{n-2} \dots a_1 $。
推导过程
设 \(K\) 为处理木头所需的代价,\(a_m\) 为第一个大于等于 \(K\) 的点的坐标,\(P\) 为代价,考虑以下两个区间:
\(\left (a_m,a_n \right ]\):
在这个区间内,不难看出,对于所有的点 \(a_i\),直接运输总是优于处理过后"滚雪球"运输,因为对于每一个树,完全可以用小于 \(K\) 的代价来完成运输。所以这个区间的代价最小和为 \(P_{\min}= \sum_{i=m-1}^{n}a_i\)。
\(\left [a_1,a_m \right ]\):
我们考虑递推(实质与 dp 差不多,不过没有数组):
假设 \(P_{i_{\min}}\) 为只考虑坐标最大的\(i\)棵树时最小花费,不难看出,\(P_{1_{\min}}=a_1\)。
考虑 \(a_2\) 分二种情况:
1.
\(a_2\) 直接搬走,此时只用考虑 \(P_{1_{\min}}\),这时 \(P_2=a_2+P_{1_{\min}}\)。
2.
\(a_2\) 与 \(a_1\) 处理后进行”滚雪球“式运输,这时 \(P_2=a_1+2K\)。
考虑了以上两种情况后,可得 \(P_{2_{\min}}=\min(a_1+2K,a_2+P_{1_{\min}})\)。
递推式
可得 \(P_{i_{\min}}=\min(a_1 + i \times K,a_i+P_{i-1_{\min}})\)。
观察可知这个区间的递推式同样适用于第一个区间,所以可以合并处理。
code
#include <bits/stdc++.h>
using namespace std;
bool cmp(int x,int y){return x>y;}
long long carica(int N, int K, vector<int> A) {
sort(A.begin(),A.end(),cmp);//保证单调递减
long long p=A[0];//考虑a1时的最小值
for(long long i=1;i<N;i++){
p=min(A[0]+(i+1)*K,A[i]+p);
}
return p;
}

浙公网安备 33010602011771号