-
描述
给一个整数数组,调整每个数的大小,使得相邻的两个数的差不大于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少。 -
注意事项
你可以假设数组中每个整数都是正整数,且小于等于100。 -
样例
对于数组[1, 4, 2, 3]和target=1,最小的调整方案是调整为[2, 3, 2, 3],调整代价之和是2。返回2。 -
标签
动态规划 背包问题 LintCode 版权所有
解决思路
对于数组 A 的中任意一个数,我们都可以随意调整,只要调整之后保证和相邻两个数的差不大于target。
状态:
如果采用动态规划,状态f(i)(j)很可能表示第i个数,转换为j,并且i之前的所有数都满足相邻之差不大于target,的最小代价。
状态转移:
f
(
i
)
(
j
)
=
m
i
n
(
f
(
i
−
1
)
(
x
)
+
∣
j
−
A
[
i
]
∣
;
∣
j
−
x
∣
<
=
t
a
r
g
e
t
f(i)(j) = min( f(i-1)(x) + |j - A[i]| ; |j-x| <= target
f(i)(j)=min(f(i−1)(x)+∣j−A[i]∣;∣j−x∣<=target
f(i)(j)最小代价等于,i-1个数转换为x( 保证x和j的差小于target) 的最小代价,加上A[i]转换为j的代价.
初始值:
f(i)(0) = A[i]:将A[i] 转换为0的最小代价等于A[i].
f(1)(j) :将A[0] 转换为0的代价等于|j - A[0]|;把f(0)(j) 置为0时, f(1)(j) = min( f(0)(x) + |j - A[i]| = |j - A[0]|
answer:
m
i
n
f
(
n
)
(
x
)
;
0
<
=
x
<
=
100
min f(n)(x); 0<=x <= 100
minf(n)(x);0<=x<=100
C++ 代码
class Solution {
public:
int minAdjustCost(vector<int> A,int target) {
if (A.empty() || target >= 100)
return 0;
vector<vector<int>> dp(A.size() + 1, vector<int>(101, 0));
for (int i = 1; i <= A.size(); i++)
{
dp[i][0] = A[i-1];
for (int j = 1; j<=100;j ++)
{
int subStart = std::max(0, j - target ) ;
int subEnd = std::min(100, j + target );
int subMinCost = 100;
for (int x = subStart; x < subEnd; x++)
if (dp[i - 1][x] < subMinCost)
subMinCost = dp[i - 1][x];
dp[i][j] = subMinCost + std::abs(j - A[i - 1]);
}
}
int minCost = 100;
for (int i = 0; i <= 100; i++)
if (dp[A.size()][i] < minCost)
minCost = dp[A.size()][i];
return minCost;
}
};
int main()
{
Solution so;
vector<int> arr = { 1,4,2,3 };
int ret = so.minAdjustCost(arr, 1);
cout << ret << endl;
system("pause");
return 0;
}