题目链接
题目思路
如果只考虑非严格单调上升,那么必定所有元素变化完之后必定还是属于原来元素的子集
可以仔细思考下得出
而如果是单调上升,可以让\(a[i]=a[i]-i\) 然后\(dp\)即可
设\(dp[i][j]\)表示第\(i\)个元素为\(b[j]\)的最小答案
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=3e3+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n;
int a[maxn],b[maxn];
ll dp[maxn][maxn];
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]=a[i]-i;
b[i]=a[i];
}
memset(dp,0x3f,sizeof(dp));
sort(b+1,b+1+n);
dp[0][1]=0;
for(int i=1;i<=n;i++){
ll mi=INF;
for(int j=1;j<=n;j++){
mi=min(mi,dp[i-1][j]);
dp[i][j]=min(dp[i][j],mi+abs(a[i]-b[j]));
}
}
ll ans=INF;
for(int i=1;i<=n;i++){
ans=min(ans,dp[n][i]);
}
printf("%lld\n",ans);
return 0;
}