这可以使用自上而下的方法来解决。
您从第一行的某个位置开始,然后从那里向下遍历。你有两个选择:
a) 在同一列上继续 - 但您需要考虑到您有足够的行用于 K 开关。所以你的条件应该是remaining_rows >= K 然后你可以选择这个选项,否则不行。
b) 将您的列切换到任何其他列。考虑所有列。
在这两个选项中取最小值。
那么递归方程将是:
getMin(r, c, K) = min(
(R - (r+1) >= K ? getMin(r+1, c, K) + A[r][c] : A[r][c] ),
( for all j != c, j < C: min(getMin(r+1, c, K-1)) )
)
其中A 是输入矩阵,R 是行数,C 是A 中的列数。
并且你对所有c = 0 到C 取最小的getMin(0, c, K )
您可以记住每个r, c, K的解决方案。
对于 K = 0 ,只需向下遍历列并得到总和。
Java 中的代码是:
class Main {
private static int[][][] dp;
public static void main(String[] args) {
int[][] A = { { 0, 1, 2 }, { 4, 3, 1 }, { 6, -2, 5 }, { 1, 4, -3 } };
int K = 3;
dp = new int[A.length][A[0].length][K + 1];
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A[0].length; j++) {
for (int k = 1; k <= K; k++) {
dp[i][j][k] = Integer.MAX_VALUE;
}
}
}
int res = Integer.MAX_VALUE;
for (int j = 0; j < A[0].length; j++)
res = Math.min(res, getMin(A, 0, j, K));
System.out.println(res);
}
private static int getMin(int[][] A, int r, int c, int K) {
int R = A.length, C = A[0].length;
if (r > R - 1 || c > C - 1)
return Integer.MAX_VALUE;
if (K == 0) {
int sum = 0;
for (int i = r; i < R; i++)
sum += A[i][c];
return sum;
}
if (dp[r][c][K] != Integer.MAX_VALUE)
return dp[r][c][K];
int min = Integer.MAX_VALUE;
int rem_rows = R - (r + 1);
for (int j = 0; j < C; j++) {
if (j == c && rem_rows >= K) {
int s = getMin(A, r + 1, j, K);
if (s != Integer.MAX_VALUE) {
min = Math.min(min, s + A[r][c]);
} else {
min = Math.min(min, A[r][c]);
}
} else if (j != c) {
int m = getMin(A, r + 1, j, K - 1);
if (m != Integer.MAX_VALUE) {
min = Math.min(min, m + A[r][c]);
} else {
min = Math.min(min, A[r][c]);
}
}
}
dp[r][c][K] = min;
return min;
}
}
你可以玩live code here