Codeforces 713C Sonya and Problem Wihtout a Legend DP(經典)
阿新 • • 發佈:2019-02-18
題意:給出長度為n的序列a,op:將任意一個數增大/減小1.
n<=3000,a[i]<=1e9,問使序列a嚴格遞增所需要的最少op次數
當a遞增時:a[i]<a[i+1] a[i]<=a[i+1]-1 a[i]-i<=a[i+1]-(i+1)
也就是b[i]=a[i]-i非遞減.同樣b非遞減時,a也就是遞增的.轉為求使b非遞減最小代價
n<=3000,a[i]<=1e9,問使序列a嚴格遞增所需要的最少op次數
當a遞增時:a[i]<a[i+1] a[i]<=a[i+1]-1 a[i]-i<=a[i+1]-(i+1)
也就是b[i]=a[i]-i非遞減.同樣b非遞減時,a也就是遞增的.轉為求使b非遞減最小代價
序列b非遞減,則最後b中元素都為原來的某些元素(歸納法證).設dp[i][j]:前i個元素變非遞減,第i個元素為原來第j大時的最小代價.
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e3+20; const ll inf=2e16; ll n,a[N],b[N]; ll dp[N][N]; int main() { while(cin>>n) { for(int i=1;i<=n;i++) scanf("%I64d",&a[i]),a[i]-=i,b[i]=a[i]; sort(b+1,b+1+n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dp[i][j]=inf; dp[0][0]=0; for(int i=1;i<=n;i++) { ll mn=inf; for(int j=1;j<=n;j++) { //dp[i][j]=min(dp[i][j],dp[i-1][k]+abs(a[i]-b[j]));k<=j mn=min(mn,dp[i-1][j]); dp[i][j]=mn+abs(a[i]-b[j]); } } ll ans=inf; for(int i=1;i<=n;i++) ans=min(ans,dp[n][i]); cout<<ans<<endl; } return 0; }