您的位置:首页 > 其它

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

2016-12-04 17:04 411 查看
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
7
2 1 5 11 5 9 11


output
9


input
5
5 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[i−1][k]),k≤j

表示前i个数字,最后一个最大的是j,然后前i−1个,就选择k≤j并且花费最小的那个

O(n2)的状态,可以用前缀和优化O(1)的转移

蓝儿如何转化为不严格递增呢,ai−aj≥i−j,i≥j

ai−i≥aj−j

所以把ai=ai−i就能不严格递增的做了

直接考虑结果的整个数列 必然存在那么几个数 他是从始至终 都没有变过 那么假设有一些数会受到这个数影响 比如一个数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 ll
ll a[maxn], b[maxn], dp[maxn][maxn]; //因为每个数都在1e9范围内,所以要用ll
int 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
[j], ans);  //看哪个结尾最小
}
cout << ans << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: