繁体   English   中英

最低调整成本

[英]Minimum Adjustment Cost

我正在尝试解决这个问题:

给定一个 integer 数组,调整每个整数,使每个相邻整数的差不大于给定的数字目标。

如果调整前的数组是A,调整后的数组是B,你应该最小化`| A[i]-B[i] |。 您可以假设数组中的每个数字都是正数 integer 且不大于 100。

`

我看到了一个 dp 解决方案,但我不太了解递归方程。

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;
}

有人可以向我解释吗?

您需要最小化调整的成本,这是您增加/减少每个元素的值,使得每个相邻元素之间的差异小于或等于target dp 解决方案是尝试每个可能的值并最小化有效值的成本(当abs(A[i]-A[i-1]) <= target时)

首先是将第一个元素调整为 1-100 的成本,在此处完成:

 for (int i = 0; i < size; i++) {
        for (int j = 1; j <= 100; j++) {
            D[i][j] = Integer.MAX_VALUE; // fill with MAX_VALUE because we want to minimize
            if (i == 0) {
                // for the first element we just set the cost of adjusting A[i] to j
                D[i][j] = Math.abs(j - A.get(i));
            }

现在您将D[0][j]作为将第一个元素调整为j的成本。 然后对于每个其他元素,您再次循环(从k = 1k = 100 )其他元素并尝试将A[i]更改为j 然后您检查abs(kj)是否有效(小于或等于target )然后您可以将A[i]调整为j并将A[i-1]调整为k以便最小化D[i][j] .

这里D[i][j]表示将A[i]更改为j的成本, D[i-1][k]是将A[i-1]更改为k的成本。 因此,对于每个kj如果它们是有效的( abs(kj)<=target ),那么你将它们加在一起并最小化保存在D[i][j]中的值,这样你就可以将它用于下一个元素,这是在这里完成的:

else {
    for (int k = 1; k <= 100; k++) {
        // if abs(j-k) > target then changing A[i] to j isn't valid (when A[i-1] is k)
        if (Math.abs(j - k) > target) {
            continue;
        }
        // otherwise, calculate the the cost of changing A[i] to j and add to it the cost of changing A[i-1] to k
        int dif = Math.abs(j - A.get(i)) + D[i - 1][k];
        // minimize D[i][j]
        D[i][j] = Math.min(D[i][j], dif);
     }
}

最后,您需要在最后一个元素处从 1 循环到 100 并检查哪个是最小值,这里完成:

int ret = Integer.MAX_VALUE;
for (int i = 1; i <= 100; i++) {
    ret = Math.min(ret, D[size - 1][i]);
}

我认为如果将初始化代码和DP计算代码分开会更容易理解,例如:

// fill the initial values
for (int i = 0; i < size; ++i) {
    for (int j = 1; j <= 100; ++j) {
        // on the first element just save the cost of changing
        // A[i] to j
        if (i == 0) {
            DP[i][j] = abs(j-A.get(i));
        } else {
            // otherwise intialize with MAX_VALUE
            D[i][j] = Integer.MAX_VALUE;        
        }

    }
}
for (int i = 1; i < size; i++) {
    for (int j = 1; j <= 100; j++) {
        for (int k = 1; k <= 100; k++) {
            // if abs(j-k) isn't valid skip it
            if (Math.abs(j - k) > target) {
                continue;
            }
            // if it is valid, calculate the cost of changing A[i] to j
            // and add it to the cost of changing A[i-1] to k then minimize
            // over all values of j and k
            int dif = Math.abs(j - A.get(i)) + D[i - 1][k];
            D[i][j] = Math.min(D[i][j], dif);
        }
    }
}

// calculate the minimum cost at the end
int ret = Integer.MAX_VALUE;
for (int i = 1; i <= 100; i++) {
    ret = Math.min(ret, D[size - 1][i]);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM