CodeForces - 713C Sonya and Problem Wihtout a Legend ( DP )

题意:

将给出的数组转化为单调递增的数组所花费的最小代价(代价为每个数改变的大小之和)

分析:

首先这个题就是POJ3666的一个变型,

POJ3666是计算的非严格的单调递增

先说POJ3666的解法:

dp[i][j] 表示将第 i 个数转化为第 j 个数所花费的最小值,( j 所代表的是排序后有序递增的一个数组)

那么dp[i][j]=dp[i-1][k]+cost(i,j)    (k<=j)

这样算下来是一个非严格的单调递增序列。

因为这个题要计算的是严格的,所以刚开始让 a[i]-i 即每个数都减去他的下标,那么就可以转化为严格单调的序列了。

#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;
}
扫描二维码关注公众号,回复: 5921430 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_40679299/article/details/89179785