1 条题解

  • 0
    @ 2025-2-22 13:17:25

    先看范围,我们只能采用 O(nlog2n)\mathcal O(n\log_2n) 的时间复杂度。我们先要对整个序列进行排序,接下来我们要 DP。

    我们对 dpidp_i 的定义为:前面 ii 个河狸移动的最优解。

    动态规划过程

    • 考虑前 i2i-2 个河狸已经分完,ai,ai1a_i, a_{i-1} 两个分一组:最优解为其中一个河狸移动到另一个河狸的位置,距离为 aiai1a_i - a_{i-1},则 dpidp_i 可以从 dpi2+(aiai1)dp_{i-2} + (a_i - a_{i-1}) 递推。
    • 考虑前 i3i-3 个河狸已经分完,ai,ai1,ai2a_i, a_{i-1}, a_{i-2} 三个分一组:最优解为左右移动到中间河狸的位置,距离为 (aiai1)+(ai1ai2)(a_i - a_{i-1}) + (a_{i-1} - a_{i-2}),即 aiai2a_i - a_{i-2},则 dpidp_i 可以从 dpi3+(aiai3)dp_{i-3} + (a_i - a_{i-3}) 递推。

    状态转移方程:$dp_i = \min(dp_{i-2} + a_i - a_{i-1}, dp_{i-3} + a_i - a_{i-2})$,请注意,此时的 i\textbf{\textit{i}} 应大于 3\textbf3ii 要大于 33 状态转移方程才成立,那么肯定有一个边界的问题。以下是状态转移方程的边界:
    $\left\{\begin{matrix} dp_0&\gets& 0 &\text{没有河狸,不用移动}\\ dp_1&\gets& +∞ & \text{无解,设一个无穷大}\\ dp_2&\gets& a_2-a_1 &\text{两个河狸一组的情况}\\ dp_3&\gets& a_3-a_1 &\text{三个河狸一组的情况} \end{matrix}\right.$

    珍藏代码

    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long a[int(3e5+5)],dp[int(3e5+5)];
    int main(){
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		cin>>a[i];
    	}
    	sort(a+1,a+n+1);
    	dp[0]=0;
    	dp[1]=1e18;
    	dp[2]=a[2]-a[1];
    	dp[3]=a[3]-a[1];
    	for(int i=4;i<=n;i++){
    		dp[i]=min(dp[i-2]+a[i]-a[i-1],dp[i-3]-a[i-2]+a[i]);
    	}
    	cout<<dp[n]<<'\n';
    	return 0;
    }
    
    

    最后说一句我的观点:我之所以用 long long,是因为范围达到了 10910^9,加来加去有可能超过 23112^{31}-1int 类型的最大边界),所以开个 long long 保平安。

    信息

    ID
    35575
    时间
    2000ms
    内存
    1024MiB
    难度
    3
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者