题解:CF38E Let's Go Rolling!
题意
有
- 定住,花费
c_i 。 - 不定,花费为这个弹珠到左侧第一个定住弹珠的距离,设这个左侧第一个定住弹珠为
j ,即花费为x_i-x_j 。
思路
一眼线性 dp。
考虑分类讨论每一个弹珠定住或是不定住的情况,这里我定义了两个 dp 数组。
定义
这个定义想到是不难的,转移式子也不难想。
可以先尝试自己写写看再看代码。
做法
这样做是
不妨令
则
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,dp[3005][3005],f[3005],s[3005],ans=1e18;
struct node{
int x,c;
}a[3005];
bool cmp(node p,node q){
return p.x<q.x;
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].c;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i].x;
memset(dp,0x3f,sizeof(dp));
memset(f,0x3f,sizeof(f));
f[1]=a[1].c;
dp[1][1]=a[1].c;
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++){
dp[i][j]=min(dp[i][j],f[j]+(s[i]-s[j])-a[j].x*(i-j));
// cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
if(j==i-1)f[i]=min(f[i],f[j]+a[i].c);
else f[i]=min(f[i],dp[i-1][j]+a[i].c);
}
//cout<<f[i]<<" ";
}
for(int i=1;i<n;i++){
ans=min(ans,dp[n][i]);
}
cout<<min(ans,f[n]);
}