标签:
http://codeforces.com/problemset/problem/713/C
Sonya was unable to think of a story for this problem, so here comes the formal description.
You are given the array containing n positive integers. At one turn you can pick any element and increase or decrease it by 1. The goal is the make the array strictly increasing by making the minimum possible number of operations. You are allowed to change elements in any way, they can become negative or equal to 0.
The first line of the input contains a single integer n (1 ≤ n ≤ 3000) — the length of the array.
Next line contains n integer ai (1 ≤ ai ≤ 109).
Print the minimum number of operation required to make the array strictly increasing.
7
2 1 5 11 5 9 11
5
5 4 3 2 1
9
12
题目打给说给一个序列,可以进行若干次操作,每次操作选择一个数让它+1或-1,问最少要几次操作使得序列变为严格单调递增序列。
首先考虑不是严格递减的情况,这其实是个经典问题的样子,太弱都没做过。。
这个大概可以这么理解:原序列,从左到右扫过去,如果左边的大于右边的,要嘛左边的减掉使其等于右边的,要嘛右边的加上使其等于左边的。
于是就可以考虑用dp来做了:
回到原问题,原问题是求严格单调递增,这个可以转化成不严格单调递增:
这样转化可行是因为:
这个转化感觉挺神奇的。。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; long long d[3333][3333],a[3333],b[3333]; int main(){ int n; scanf("%d",&n); for(int i=1; i<=n; ++i){ scanf("%d",a+i); a[i]-=i; b[i]=a[i]; } sort(b+1,b+1+n); int bn=unique(b+1,b+1+n)-b-1; memset(d,127,sizeof(d)); for(int i=1; i<=bn; ++i){ d[1][i]=min(d[1][i-1],abs(a[1]-b[i])); } for(int i=2; i<=n; ++i){ for(int j=1; j<=bn; ++j){ d[i][j]=min(d[i][j-1],d[i-1][j]+abs(a[i]-b[j])); } } printf("%lld",d[n][bn]); return 0; }
Codeforces713C Sonya and Problem Wihtout a Legend(DP)
标签:
原文地址:http://www.cnblogs.com/WABoss/p/5876968.html