给一个整数数组,调整每个数的大小,使得相邻的两个数的差小于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少。
样例
对于数组[1, 4, 2, 3]和target=1,最小的调整方案是调整为[2, 3, 2, 3],调整代价之和是2。返回2。
注意
你可以假设数组中每个整数都是正整数,且小于等于100。
————————————————
【思路】
因为数的范围是1~100,每个数有100中调整的可能性,采用动态规划的思路。
建立大小为(n+1)*101的二维数组rec记录所有可能调整的代价,第一行初始化为全0,其他行为最大值。
rec中第i行对应A[i-1]。对于每个数A[i],调整后的结果有100种,用rec[i][j]表示数字A[i]调整为j的最小代价。对于每个rec[i][j],A[i-1]调整到k的代价加上A[i]调整到j的最小代价即为rec[i][j]的代价。而k又有100种选择,对于j,当|j-k|的绝对值不大于target时,代价最小,当前rec[i][j]为rec[i-1][k] +( j - A[i-1]),rec[i][j]保留所有可能代价中的最小代价。
最后,rec[n][0~100]中的最小代价即为对整个数组调整后的最下代价。
————————————————
class Solution {
public:
/**
* @param A: An integer array.
* @param target: An integer.
*/
int MinAdjustmentCost(vector<int> A, int target) {
// write your code here
int n = A.size();
vector<vector<int> > rec(n+1, vector<int> (101, numeric_limits<int>::max()));
//初始化第一行为0
//rec[i][j]表示第i个数调整到j的最小代价,k表示相邻两个数调整到某个值的所有可能
rec[0] = vector<int>(101, 0);
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= 100; ++j) {
for (int k = 0; k <= 100; k++) {
//如果k在target范围内,更新rec[i][j]的值为上一个数到k的代价,加上当前数到j的代价
if (abs(j-k) <= target)
rec[i][j] = min(rec[i-1][k] + abs(A[i-1]-j), rec[i][j]);
}
}
}
int cost = numeric_limits<int>::max();
for (int i = 0; i <= 100; ++i) {
cost = min(cost, rec[n][i]);
}
return cost;
}
};
class Solution {
public:
/
**
* @ param
A: An
integer
array.
* @ param
target: An
integer.
* /
int
MinAdjustmentCost(vector < int > A, int
target) {
// write
your
code
here
int
n = A.size();
if (n < 2)
{
return 0;
}
int
buf[n][101];
for (int i = 1; i <= 100; i++)
{
buf[0][i] = abs(i - A[0]);
}
for (int i = 1; i < n; i++)
{
for (int j = 1; j <= 100; j++)
{
int
left = max(j - target, 1);
int
right = min(j + target, 100);
buf[i][j] = INT_MAX;
for (int k = left; k <= right; k++)
{
buf[i][j] = min(buf[i][j], buf[i-1][k]+abs(A[i]-j));
}
}
}
int
result = INT_MAX;
for (int i = 1; i <= 100; i++)
{
result = min(result, buf[n - 1][i]);
}
return result;
}
};