poj3666
题意:给出一个序列a,用最小的花费将序列变为非严格递增序列b。修改一个数的花费为该数修改前后差值的绝对值。abs(b[i]-a[i])
思路:
为使花费最小,修改后序列的每个值b[i]必为原序列a中的数。
dp[i][j]表示前i个数满足非严格递增,a[i]=b[j]情况下花费最小值。
转移方程dp[i][j]=min(dp[i-1][k])+abs(a[i]-b[j]; (k<=j)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2005;
int a[maxn],b[maxn],dp[maxn][maxn];
int main() {
int n,tmp,ans=1e9;
scanf("%d",&n);
for(int i=1;i<=n;++i) {
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
memset(dp,0,sizeof dp);
for(int i=1;i<=n;++i) dp[1][i]=abs(a[1]-b[i]);
for(int i=2;i<=n;++i) {
tmp=dp[i-1][1];
for(int j=1;j<=n;++j) {
tmp=min(tmp,dp[i-1][j]);
dp[i][j]=tmp+abs(a[i]-b[j]);
}
}
for(int i=1;i<=n;++i) ans=min(ans,dp[n][i]);
printf("%d\n",ans);
return 0;
}
codeforces713C
题意:上题变形,序列修改为严格递增序列。
tip:a[i]=a[i]-i;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3005;
ll a[maxn],b[maxn],dp[maxn][maxn];
int main() {
int n;
ll tmp,ans=1e15;
scanf("%d",&n);
for(int i=1;i<=n;++i) {
scanf("%d",&a[i]);
a[i]=a[i]-i;
b[i]=a[i];
}
sort(b+1,b+1+n);
for(int i=1;i<=n;++i) dp[1][i]=abs(a[1]-b[i]);
for(int i=2;i<=n;++i) {
tmp=dp[i-1][1];
for(int j=1;j<=n;++j) {
tmp=min(dp[i-1][j],tmp);
dp[i][j]=tmp+abs(a[i]-b[j]);
}
}
for(int i=1;i<=n;++i) ans=min(ans,dp[n][i]);
printf("%I64d\n",ans);
return 0;
}