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;
}
我们会走到一起的。

浙公网安备 33010602011771号