Given an integer array, adjust each integers so that the difference of every adjacent integers are not greater than a given number target.
If the array before adjustment is A, the array after adjustment is B, you should minimize the sum of|A[i]-B[i]|
Notice
You can assume each number in the array is a positive integer and not greater than 100
.
Given [1,4,2,3]
and target = 1
, one of the solutions is [2,3,2,3]
, the adjustment cost is 2
and it's minimal.
Return 2
.
转自http://www.cnblogs.com/yuzhangcmu/p/4153927.html
这道题真的惭愧,确实没有想出来
可以用递归和动态规划来解决这道题
递归,有点像word ladder和数独一样代码如下
/**
* @param A: An integer array.
* @param target: An integer.
*/
public static int MinAdjustmentCost1(ArrayList<Integer> A, int target) {
// write your code here
if (A == null) {
return 0;
}
return rec(A, new ArrayList<Integer>(A), target, 0);
}
/*
* SOL 1:
* 最普通的递归方法。
* */
public static int rec(ArrayList<Integer> A, ArrayList<Integer> B, int target, int index) {
int len = A.size();
if (index >= len) {
// The index is out of range.
return 0;
}
int dif = 0;
int min = Integer.MAX_VALUE;
// If this is the first element, it can be from 1 to 100;
for (int i = 0; i <= 100; i++) {
if (index != 0 && Math.abs(i - B.get(index - 1)) > target) {
continue;
}
B.set(index, i);
dif = Math.abs(i - A.get(index));
dif += rec(A, B, target, index + 1);
min = Math.min(min, dif);
// 回溯
B.set(index, A.get(index));
}
return min;
}
更好的解法用动态规划,dp[i][[j] i表示现在loop到的位置,j表示1-100的数字,dp[i][j]表示,当loop到i位置时,取j值时整个修改的最小值
所以最终的结果要 比较 dp[A.size()-1][1--100]的大小来决定整个变换的最小值, 这个有点像刷颜色的问题
/*
* SOLUTION 4:
* DP
* */
/**
* @param A: An integer array.
* @param target: An integer.
*/
public static int MinAdjustmentCost(ArrayList<Integer> A, int target) {
// write your code here
if (A == null || A.size() == 0) {
return 0;
}
// D[i][v]: 把index = i的值修改为v,所需要的最小花费
int[][] D = new int[A.size()][101];
int size = A.size();
for (int i = 0; i < size; i++) {
for (int j = 1; j <= 100; j++) {
D[i][j] = Integer.MAX_VALUE;
if (i == 0) {
// The first element.
D[i][j] = Math.abs(j - A.get(i));
} else {
for (int k = 1; k <= 100; k++) {
// 不符合条件
if (Math.abs(j - k) > target) {
continue;
}
int dif = Math.abs(j - A.get(i)) + D[i - 1][k];
D[i][j] = Math.min(D[i][j], dif);
}
}
}
}
int ret = Integer.MAX_VALUE;
for (int i = 1; i <= 100; i++) {
ret = Math.min(ret, D[size - 1][i]);
}
return ret;
}
刷墙的问题:对比起来真是一模一样
class Solution {
public:
/**
* @param costs n x 3 cost matrix
* @return an integer, the minimum cost to paint all houses
*/
int minCost(vector<vector<int>>& costs) {
// Write your code here
if (costs.size() == 0) //检查边界条件非常重要
return 0;
int n = costs.size();
vector<vector<int>> dp(n, vector<int>(3));
//dp[i][j] 表示计算到第i户时,他选择第j种颜色图墙时的最小价钱
for (int i=0; i<3; i++)
{
dp[0][i] = costs[0][i];
}
for (int i=1; i<n; i++)
{
for (int j=0; j<3; j++)
{
int minC = INT_MAX;
for (int k=0; k<3; k++)
{
if (k != j)
{
minC = min(minC, dp[i-1][k]);
}
dp[i][j] = minC + costs[i][j];
}
}
}
int minRet = INT_MAX;
for (int i=0; i<3; i++)
{
minRet = min(minRet, dp[n-1][i]);
}
return minRet;
}
};