CF13C Sequence
給定\(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;
}
附:jiaqiang版P4597 序列 sequence ~ 題解。