给定\(N\)个数,每次操作可以选其中一个数\(+1\)或\(-1\)。请问要让这个数列不降,最少需要多少次操作?
我们用DP解决。
对\(a\)从小到大排序,存在\(c\)中。
我们用\(f[i][j]\)表示让前\(i\)个元素满足条件,而且这些元素最大值不超过\(c[j]\)的最小操作次数。
状态转移方程:\(f[i][j]=\min(f[i][j-1],f[i-1][j]+abs(a[i]-c[j]))\)。
最终答案就是\(\min(f[n][i])\)。
时间复杂度\(O(n^2)\)。
注意:
- 空间限制64MB,需要滚动数组。
- 开
long long
。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[5010],b[5010];
int f[2][5010];
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+1+n);
f[0][0]=f[1][0]=LLONG_MAX;
bool pos=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
f[pos][j]=min(f[pos][j-1],f[!pos][j]+abs(a[i]-b[j]));
}
pos=!pos;
}
int ans=LLONG_MAX;
for(int i=1;i<=n;i++){
ans=min(ans,f[!pos][i]);
}
cout<<ans;
return 0;
}
附:强化版P4597 序列 sequence ~ 题解。
标签:5010,Sequence,int,题解,long,CF13C From: https://www.cnblogs.com/Sinktank/p/18169206