1 条题解

  • 0
    @ 2025-8-24 23:09:31

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar FFTotoro
    龙猫

    搬运于2025-08-24 23:09:31,当前版本为作者最后更新于2025-02-08 11:30:48,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    之前把这题搬进了模拟赛,直接把当时写的题解弄过来。

    本题有结论:将坐标序列排序后,最终河狸聚成的形态必然形如“将连续的 22 只河狸或 33 只河狸分成一组”。如果将 44 只或更多只河狸移动到同一个位置,那么必然不优——以 44 只河狸为例,假设坐标分别为 a1,a2,a3,a4(a1a2a3a4)a_1,a_2,a_3,a_4(a_1\le a_2\le a_3\le a_4),那么如果全部移动到同一个位置,代价为 a1a2+a2a3+a2a4|a_1-a_2|+|a_2-a_3|+|a_2-a_4|,但是如果将它们两两分组,代价就为 a1a2+a3a4|a_1-a_2|+|a_3-a_4|,显然后者不大于前者;更多只的情况可以类似地推导。

    所以我们可以先将 aa 排序,在这之后进行动态规划。设 fif_i 为考虑了前 ii 只河狸的最小代价,那么有如下两种转移:

    • fifi2+aiai1f_i\gets f_{i-2}+a_i-a_{i-1};(将 i1i-1ii 分组)
    • fifi3+aiai2f_i\gets f_{i-3}+a_i-a_{i-2};(将 i2i-2i1i-1ii 分组)

    时间复杂度为 O(nlogn)O(n\log n)

    放代码:

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
      ios::sync_with_stdio(false);
      int n; cin>>n;
      vector<int> a(n),f(n);
      for(auto &i:a)cin>>i;
      sort(a.begin(),a.end());
      f[1]=a[1]-a[0],f[2]=a[2]-a[0];
      for(int i=3;i<n;i++)
        f[i]=min(f[i-2]+a[i]-a[i-1],i>3?f[i-3]+a[i]-a[i-2]:(int)2e9); // 进行 DP
      cout<<f[n-1]<<endl;
      return 0;
    }
    
    • 1

    信息

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