#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int M=4100;
const int inf=1<<30;
int n,a[M],b[M]; //因为花费要最小->修改后的数肯定为原数组中的某个数(反证)-> b[j] 原数组第j小的数
long long int dp[2][M]; // dp[i][j] 将前i个数变为 monotonic时 把第i个数变为第J小时的最小花费
// dp[i][j] =min(dp[i-1][k])+abs(a[i]-b[j]) k<=j (非递减时:第i-1个数不能比第i个数大)
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+n+1);
for(int j=1;j<=n;j++)
{
dp[0][j]=abs(a[1]-b[j]);
}
for(int i=2;i<=n;i++)
{
long long t=dp[(i-1)&1][1];// 记录k=1~j-1中最小的 dp[i-1][k]
for(int j=1;j<=n;j++)
{
t=min(t,dp[(i-1)&1][j]);
dp[i&1][j]=t+abs(a[i]-b[j]); //滚动优化
}
}
long long ans=inf;
for(int j=1;j<=n;j++)
{
ans=min(ans,dp[n&1][j]);
}
cout<<ans<<endl;
return 0;
}
poj 3666 线性dp
最新推荐文章于 2020-07-21 17:05:28 发布