Codeforces 713C C. Sonya and Problem Wihtout a Legend (经典DP)

来源:互联网 发布:整站源码带数据下载 编辑:程序博客网 时间:2024/06/08 17:51


C. Sonya and Problem Wihtout a Legend
time limit per test
5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Input

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).

Output

Print the minimum number of operation required to make the array strictly increasing.

Examples
input
72 1 5 11 5 9 11
output
9
input
55 4 3 2 1
output
12
Note

In the first sample, the array is going to look as follows:

2 3 5 6 7 9 11

|2 - 2| + |1 - 3| + |5 - 5| + |11 - 6| + |5 - 7| + |9 - 9| + |11 - 11| = 9

And for the second sample:

1 2 3 4 5

|5 - 1| + |4 - 2| + |3 - 3| + |2 - 4| + |1 - 5| = 12

这个题跟poj3666是同一个类型只是这个是严格的,那个不必严格的





++
 
 
 
n 
 
x 
 
dp[i][j]=abs(b[i]a[j])+min(dp[i1][k]),kj 
iji1kj 
O(n2)O(1) 
aiajij,ij 
aiiajj 
ai=aii


直接考虑结果的整个数列   必然存在那么几个数  他是从始至终 都没有变过  那么假设有一些数会受到这个数影响 比如一个数ai不变 如果aj 是受ai影响 那么就会消耗  

先考虑这样一个问题,如果是非严格单调递增该如何做,我们会发现每次调整,都是调整某个数字为原先数列中存在的数字,最后才是最优的,所以,我们设DP[i][j]表示前i个数字,最后一个数为原先数列排序后第j大的数字的最小代价,那么做一遍n2的DP就能够获得答案,现在题目中要求的是严格单调递增,那么就用到一种经典的处理方法,a[i]=a[i]-i,这样子就转化为非严格单调的问题了。


#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 3e3 + 5;const ll INF = 0x7fffffffffffffff; //这里不是const int 是 const llll a[maxn], b[maxn], dp[maxn][maxn]; //因为每个数都在1e9范围内,所以要用llint main(){    int n;    cin >> n;    for(int i = 1; i <= n; i++)    {        cin >> a[i];        a[i] -= i;   //这里就是把严格递增转换成非严格递增        b[i] = a[i];    }    sort(b+1, b+n+1);    for(int i = 1; i <= n; i++)    {        ll min1 = INF;           for(int j = 1; j <= n; j++)        {            min1 = min(min1, dp[i-1][j]);  //这个min1表示的就是i-1个数并且最后一个数小于等于b[j]的最小值,这种记录方式很好            dp[i][j] = min1 + abs(a[i]-b[j]);        }    }    ll ans = INF;    for(int j = 1; j <= n; j++)    {        ans = min(dp[n][j], ans);  //看哪个结尾最小    }    cout << ans << endl;    return 0;}


1 0
原创粉丝点击