题解: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;
}
posted @ 2026-03-08 10:11  Sk_luoying  阅读(30)  评论(0)    收藏  举报