题意
给一个整数数组,调整每个数的大小,使得相邻的两个数的差不大于一个给定的整数target
,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少。
你可以假设数组中每个整数都是正整数,且小于等于100。
样例 1:
输入: [1,4,2,3], target=1
输出: 2
样例 2:
输入: [3,5,4,7], target=2
输出: 1
题目分析
可以证明最优策略中每一个元素也一定不超过100, 否则将最优策略中小于1的数改成1,大于100的数改成100,总的修改代价更小且仍然满足任意两个相邻元素的差不超过Target。
1. 确定状态
最后一步:
将 A A A改成 B B B, A [ n − 1 ] A[n-1] A[n−1]改成 x x x,这一步的代价是 ∣ A [ n − 1 ] − x ∣ |A[n-1]-x| ∣A[n−1]−x∣,需要确保 ∣ x − B [ n − 2 ] ∣ ≤ T a r g e t |x-B[n-2]|≤Target ∣x−B[n−2]∣≤Target
子问题:
前面 n − 1 n-1 n−1个元素, A [ 0... n − 2 ] A[0...n-2] A[0...n−2]改成 B [ 0.. n − 2 ] B[0..n-2] B[0..n−2],需要知道最小代价并且确保 B [ 0... n − 2 ] B[0...n-2] B[0...n−2]中任意两个相邻元素的差不超过 T a r g e t Target Target。
有一个问题,改 A [ n − 1 ] A[n-1] A[n−1]时不知道 B [ n − 2 ] B[n-2] B[n−2]是多少,只有知道了 B [ n − 2 ] B[n-2] B[n−2],才能确定 A [ n − 1 ] A[n-1] A[n−1]改成了 B [ n − 2 ] − T a r g e t 和 B [ n − 2 ] + T a r g e t B[n-2]-Target和B[n-2]+Target B[n−2]−Target和B[n−2]+Target 之间。——不知道多少,就保存下来。序列+状态
状态:
设状态f[i][j] 为将A前i个元素给成B的最小代价。确保前i个元素任意两个相邻的元素不超过Target,并且A[i-1]改成了j 。序列+状态
2. 转移方程
f [ i ] [ j ] = m i n j − T a r g e t < = k < = 100 ( f [ i − 1 ] [ k ] + ∣ j − A [ i − 1 ∣ ) f[i][j] = min_{j-Target<=k<=100}(f[i-1][k]+|j-A[i-1|) f[i][j]=minj−Target<=k<=100(f[i−1][k]+∣j−A[i−1∣)
( f [ i − 1 ] [ k ] ) (f[i-1][k]) (f[i−1][k]) :将A前i-1个元素改成B的最小代价,其中A[i-2]改成了k
( ∣ j − A [ i − 1 ∣ ) (|j-A[i-1|) (∣j−A[i−1∣) : A[i-1]改成j的代价
3. 初始条件
A的第一个元素可以变换成任意一个数字,因为之前没有相邻的元素
f [ 1 ] [ j ] = ∣ j − a [ 0 ] ∣ , ( j = 1 , 2 , . . . 100 ) f[1][j]=|j-a[0]|, (j=1,2,...100) f[1][j]=∣j−a[0]∣,(j=1,2,...100)
4. 计算顺序
- 前一个、前两个、…
- 答案是: m i n f [ N ] [ 1 ] , . . . . f [ N ] [ 100 ] min{f[N][1],....f[N][100]} minf[N][1],....f[N][100]
- 时间: O ( 10 0 2 N ) O(100^2 N) O(1002N)
- 空间: O ( 100 N ) O(100N) O(100N)
- 滚动数组: O ( 100 ) O(100) O(100)