Вам необходимо минимизировать стоимость уравнивания, то есть значение, которое вы увеличиваете / уменьшаете для каждого элемента, так что разница между всеми соседними элементами меньше или равна 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 = 1
до k = 100
) для других элементов и пытаетесь изменить A[i]
на j
. Затем вы проверяете, действительно ли abs(k-j)
(меньше или равно 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
. поэтому для каждых k
и j
, если они действительны (abs(k-j)<=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]);
}