函数最值2

来源:互联网 发布:ubuntu开机网卡自启动 编辑:程序博客网 时间:2024/05/22 12:15

这里写图片描述
二分+DP
二分挺好想,只是DP 的 Check让人难以理解。
DP[i]表示i不改变的最小修改的元素个数

转移?DP[i]=i-1//显然枚举1->i-1如果abs(a[i]-a[j])<=mid*(i-j) DP[i]=min(DP[j]+i-j-1)//改中间的数为什么?假如abs(a[i]-a[j])>mid*(i-j),不可能通过调整中间的数来使得区间内的值小于<=mid而当abs(a[i]-a[j])<=mid*(i-j),可以通过调整中间区间的值给搞成相同的去满足要求
#include <cstdio>#include <iostream>#include <cmath>using namespace std;int dp[2010],a[2010];int n,k;bool check(int mid){    int ans=n+1;    for(int i=1;i<=n;i++)    {        dp[i]=i-1;        for(int j=1;j<i;j++)        if(abs(a[i]-a[j])<=1ll*(mid*(i-j)))         dp[i]=min(dp[i],dp[j]+i-j-1);//大于了怎么改都不成立         ans=min(ans,dp[i]+n-i);//假设后面改掉     }    return ans<=k ;}int main(){    int n,k;    scanf("%d%d",&n,&k);    for(int i=1;i<=n;i++)     scanf("%d",&a[i]);    int l=0,r=1e8,ans=0;    while(l<=r)    {        int mid=(l+r)/2;        if(check(mid)) ans=mid,r=mid-1;        else l=mid+1;    }    printf("%d",ans);    return 0;}