CF38E

首先将弹珠按坐标从小到大排序。设 \(f_i\) 表示前 \(i\) 颗弹珠,强制固定第 \(i\) 颗弹珠的最小代价,则有显然的转移:

\[f_i=\min_{1\le j <i}f_j+\sum_{k=j+1}^{i-1}(x_k-x_j)+c_i \]

将和式展开,使用前缀和维护 \(x_k\) 的和,可以做到 \(O(n^2)\)。可以在最后再放入一颗弹珠 \(n+1\) 并令 \(c_{n+1}=0\),可以避免边界问题。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
struct P{
    int x,c;
    bool operator<(const P &A)const{
        return x<A.x;
    }
}a[10010];
int n,s[10010],f[10010];
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i].x>>a[i].c;
    sort(a+1,a+n+1);
    n++;
    a[n].x=a[n-1].x+1;
    a[n].c=0;
    for(int i=1;i<=n;i++){
        s[i]=s[i-1]+a[i].x;
        f[i]=f[i-1]+a[i].c;
        for(int j=1;j<i;j++)
            f[i]=min(f[i],f[j]+(s[i-1]-s[j])-a[j].x*(i-j-1)+a[i].c);
        // cout<<f[i]<<endl;
    }
    cout<<f[n];
    return 0;
}
posted @ 2025-09-12 19:40  FormulaOne  阅读(10)  评论(0)    收藏  举报