函式最值2
阿新 • • 發佈:2022-12-10
目錄
題目描述
對於一個數組 \(A\) 定義 \(F(A)=max{abs(a[i]−a[i+1])};\) 給定一個數組,最多修改其中 \(k\) 個元素,只能把數修改成整數,求 \(F(A)\) 的最小值。
題目分析
這題很容易想到是二分,二分 \(F(A)\)。
check 是用 dp 。
- 狀態
mid
:相鄰兩數的差不超過 \(mid\)。i
:表示搜到第 \(i\)。j
:表示 \(1~i-1\)的一個數。dp[i]
:表示 \(i\) 不改變的最小修改的元素個數。 - 初始化
很容易想到dp[i]=i-1
。 - 轉移
如果\(|a[i]-a[j]|\)小於相鄰兩數的差的最大值*差的數量,
那就改i~j中間的數使差值平均,
否則改了也不滿足條件。
所以狀態轉移方程就是:
if(abs(a[i]-a[j])<=x*(i-j))
dp[i]=min(dp[i],dp[j]+i-j-1);
要修改的個數就是sum=min(dp[i]+n-i);
(假設後面都要改)
題目程式碼
#include<bits/stdc++.h> using namespace std; const int N=1e3+10; int n,k,a[N],dp[N]; bool check(int x) { int sum=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])<=x*(i-j)) dp[i]=min(dp[i],dp[j]+i-j-1); sum=min(sum,dp[i]+n-i); } return sum<=k; } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%d",&a[i]); int l=0,r=1e9; while(l<=r) { int mid=(l+r)/2; if(check(mid))r=mid-1; else l=mid+1; } cout<<l; return 0; }