题意:
将给出的数组转化为单调递增的数组所花费的最小代价(代价为每个数改变的大小之和)
分析:
首先这个题就是POJ3666的一个变型,
POJ3666是计算的非严格的单调递增
先说POJ3666的解法:
表示将第 i 个数转化为第 j 个数所花费的最小值,( j 所代表的是排序后有序递增的一个数组)
那么
这样算下来是一个非严格的单调递增序列。
因为这个题要计算的是严格的,所以刚开始让 即每个数都减去他的下标,那么就可以转化为严格单调的序列了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=3e3+10;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll dp[maxn][maxn];
ll a[maxn],b[maxn];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
b[i]=a[i]=a[i]-i;
}
sort(b+1,b+1+n);
memset(dp,inf,sizeof dp);
for(int i=1;i<=n;i++){
dp[1][i]=abs(a[1]-b[i]);
}
ll ans=inf;
for(int i=2;i<=n;i++){
ll last=inf;
for(int j=1;j<=n;j++){
last=min(last,dp[i-1][j]);
dp[i][j]=min(dp[i][j],last+abs(b[j]-a[i]));
}
}
for(int i=1;i<=n;i++){
ans=min(ans,dp[n][i]);
}
printf("%lld\n",ans);
return 0;
}