Levko has an array that consists of integers: a1, a2, ... , an. But he doesn’t like this array at all.
Levko thinks that the beauty of the array a directly depends on valuec(a), which can be calculated by the formula:
It’s time to change the world and Levko is going to change his array for the better. To be exact, Levko wants to change the values of at mostk array elements (it is allowed to replace the values by any integers). Of course, the changes should make the array as beautiful as possible.
Help Levko and calculate what minimum number c(a) he can reach.
The first line contains two integers n andk (1 ≤ k ≤ n ≤ 2000). The second line contains space-separated integersa1, a2, ... , an ( - 109 ≤ ai ≤ 109).
A single number — the minimum value of c(a) Levko can get.
5 2 4 7 4 7 4
0
3 1 -100 0 100
100
6 3 1 2 3 7 8 9
1
In the first sample Levko can change the second and fourth elements and get array:4, 4, 4, 4, 4.
In the third sample he can get array: 1, 2, 3, 4, 5, 6.
题目大意:
最多可以修改K次数字,每次修改一个数字变成任意值,C=max(a【i+1】-a【i】);求操作之后最小的C.
思路:
1、思路来源于巨牛:http://www.cnblogs.com/DreamHighWithMe/p/3455723.html
2、我们二分C的值,然后通过处理最小改动次数,来判断当前二分中间值mid是否可行,如果可行,记录可行解,否则继续二分。
3、处理最小改动次数,考虑dp,设定dp【i】表示a【i】不进行改动,且前i个满足mid值的限定的最少改动次数。
那么不难推出其状态转移方程:
dp【i】=dp【j】+i-j-1;(表示从j到i开区间内的数据全部进行改动);那么改动的前提呢?(a【i】-a【j】<=(i-j)*mid);表示我们从a【j】到a【i】中间的数都平均开分配值,假设a【j】=1;a【i】=10,此时mid的值为2,如果从i到j中间有4个数,那么我们最好的分配方案就是:
a【j】=1;a【j+1】=3;a【j+2】=5;a【j+3】=7;a【j+4】=9;a【i】=10;将差值平均开来是最优的分配方案。
4、dp过程中,注意一些小的细节,具体参考代码。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll __int64
ll dp[2005];
ll a[2005];
ll n,k;
ll Dp_Slove(ll mid)
{
memset(dp,0x3f3f3f3f,sizeof(dp));
dp[1]=0;
for(ll i=2;i<=n;i++)
{
dp[i]=i-1;
for(ll j=i-1;j>=1;j--)
{
if(abs(a[i]-a[j])<=mid*(i-j))
{
dp[i]=min(dp[i],dp[j]+i-j-1);
}
}
if(dp[i]+n-i<=k)return 1;
}
if(dp[n]<=k)return 1;
else return 0;
}
int main()
{
while(~scanf("%I64d%I64d",&n,&k))
{
for(ll i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
ll l=0,r=2000000050;
ll ans=0;
while(r>=l)
{
ll mid=(l+r)/2;
if(Dp_Slove(mid))
{
r=mid-1;
ans=mid;
}
else l=mid+1;
}
printf("%I64d\n",ans);
}
}