- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试用 Java 实现匈牙利算法。我有一个 NxN 成本矩阵。我正在关注 this逐步指导。所以我有 costMatrix[N][N] 和 2 个数组来跟踪覆盖的行和覆盖的列 - rowCover[N]、rowColumn[N](1 表示覆盖,0 表示未覆盖)
如何用最少的行数覆盖 0?谁能指出我正确的方向?
如有任何帮助/建议,我们将不胜感激。
最佳答案
在 Wikipedia article (section Matrix Interpretation) 中检查算法的第 3 步,他们解释了一种计算最小行数以覆盖所有 0 的方法
更新:以下是获取覆盖0
的最少行数的另一种方法:
import java.util.ArrayList;
import java.util.List;
public class MinLines {
enum LineType { NONE, HORIZONTAL, VERTICAL }
private static class Line {
int lineIndex;
LineType rowType;
Line(int lineIndex, LineType rowType) {
this.lineIndex = lineIndex;
this.rowType = rowType;
}
LineType getLineType() {
return rowType;
}
int getLineIndex() {
return lineIndex;
}
boolean isHorizontal() {
return rowType == LineType.HORIZONTAL;
}
}
private static boolean isZero(int[] array) {
for (int e : array) {
if (e != 0) {
return false;
}
}
return true;
}
public static List<Line> getMinLines(int[][] matrix) {
if (matrix.length != matrix[0].length) {
throw new IllegalArgumentException("Matrix should be square!");
}
final int SIZE = matrix.length;
int[] zerosPerRow = new int[SIZE];
int[] zerosPerCol = new int[SIZE];
// Count the number of 0's per row and the number of 0's per column
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (matrix[i][j] == 0) {
zerosPerRow[i]++;
zerosPerCol[j]++;
}
}
}
// There should be at must SIZE lines,
// initialize the list with an initial capacity of SIZE
List<Line> lines = new ArrayList<Line>(SIZE);
LineType lastInsertedLineType = LineType.NONE;
// While there are 0's to count in either rows or colums...
while (!isZero(zerosPerRow) && !isZero(zerosPerCol)) {
// Search the largest count of 0's in both arrays
int max = -1;
Line lineWithMostZeros = null;
for (int i = 0; i < SIZE; i++) {
// If exists another count of 0's equal to "max" but in this one has
// the same direction as the last added line, then replace it with this
//
// The heuristic "fixes" the problem reported by @JustinWyss-Gallifent and @hkrish
if (zerosPerRow[i] > max || (zerosPerRow[i] == max && lastInsertedLineType == LineType.HORIZONTAL)) {
lineWithMostZeros = new Line(i, LineType.HORIZONTAL);
max = zerosPerRow[i];
}
}
for (int i = 0; i < SIZE; i++) {
// Same as above
if (zerosPerCol[i] > max || (zerosPerCol[i] == max && lastInsertedLineType == LineType.VERTICAL)) {
lineWithMostZeros = new Line(i, LineType.VERTICAL);
max = zerosPerCol[i];
}
}
// Delete the 0 count from the line
if (lineWithMostZeros.isHorizontal()) {
zerosPerRow[lineWithMostZeros.getLineIndex()] = 0;
} else {
zerosPerCol[lineWithMostZeros.getLineIndex()] = 0;
}
// Once you've found the line (either horizontal or vertical) with the greater 0's count
// iterate over it's elements and substract the 0's from the other lines
// Example:
// 0's x col:
// [ 0 1 2 3 ] -> 1
// [ 0 2 0 1 ] -> 2
// [ 0 4 3 5 ] -> 1
// [ 0 0 0 7 ] -> 3
// | | | |
// v v v v
// 0's x row: {4} 1 2 0
// [ X 1 2 3 ] -> 0
// [ X 2 0 1 ] -> 1
// [ X 4 3 5 ] -> 0
// [ X 0 0 7 ] -> 2
// | | | |
// v v v v
// {0} 1 2 0
int index = lineWithMostZeros.getLineIndex();
if (lineWithMostZeros.isHorizontal()) {
for (int j = 0; j < SIZE; j++) {
if (matrix[index][j] == 0) {
zerosPerCol[j]--;
}
}
} else {
for (int j = 0; j < SIZE; j++) {
if (matrix[j][index] == 0) {
zerosPerRow[j]--;
}
}
}
// Add the line to the list of lines
lines.add(lineWithMostZeros);
lastInsertedLineType = lineWithMostZeros.getLineType();
}
return lines;
}
public static void main(String... args) {
int[][] example1 =
{
{0, 1, 0, 0, 5},
{1, 0, 3, 4, 5},
{7, 0, 0, 4, 5},
{9, 0, 3, 4, 5},
{3, 0, 3, 4, 5}
};
int[][] example2 =
{
{0, 0, 1, 0},
{0, 1, 1, 0},
{1, 1, 0, 0},
{1, 0, 0, 0},
};
int[][] example3 =
{
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0},
{0, 0, 1, 1, 0, 0},
{0, 1, 1, 0, 0, 0},
{0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0}
};
List<int[][]> examples = new ArrayList<int[][]>();
examples.add(example1);
examples.add(example2);
examples.add(example3);
for (int[][] example : examples) {
List<Line> minLines = getMinLines(example);
System.out.printf("Min num of lines for example matrix is: %d\n", minLines.size());
printResult(example, minLines);
System.out.println();
}
}
private static void printResult(int[][] matrix, List<Line> lines) {
if (matrix.length != matrix[0].length) {
throw new IllegalArgumentException("Matrix should be square!");
}
final int SIZE = matrix.length;
System.out.println("Before:");
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
System.out.printf("%d ", matrix[i][j]);
}
System.out.println();
}
for (Line line : lines) {
for (int i = 0; i < SIZE; i++) {
int index = line.getLineIndex();
if (line.isHorizontal()) {
matrix[index][i] = matrix[index][i] < 0 ? -3 : -1;
} else {
matrix[i][index] = matrix[i][index] < 0 ? -3 : -2;
}
}
}
System.out.println("\nAfter:");
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
System.out.printf("%s ", matrix[i][j] == -1 ? "-" : (matrix[i][j] == -2 ? "|" : (matrix[i][j] == -3 ? "+" : Integer.toString(matrix[i][j]))));
}
System.out.println();
}
}
}
重要的部分是 getMinLines
方法,它返回一个 List
,其中包含覆盖矩阵 0
条目的行。对于示例矩阵打印:
Min num of lines for example matrix is: 3
Before:
0 1 0 0 5
1 0 3 4 5
7 0 0 4 5
9 0 3 4 5
3 0 3 4 5
After:
- + - - -
1 | 3 4 5
- + - - -
9 | 3 4 5
3 | 3 4 5
Min num of lines for example matrix is: 4
Before:
0 0 1 0
0 1 1 0
1 1 0 0
1 0 0 0
After:
| | | |
| | | |
| | | |
| | | |
Min num of lines for example matrix is: 6
Before:
0 0 0 0 0 0
0 0 0 1 0 0
0 0 1 1 0 0
0 1 1 0 0 0
0 1 0 0 0 0
0 0 0 0 0 0
After:
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
- - - - - -
我希望这能给你带来动力,匈牙利算法的其余部分应该不难实现
关于java - 匈牙利算法 : How to cover 0 elements with minimum lines?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14795111/
我是 Haskell 术语的初学者。我必须做一个显示所有最低位置的练习。 例如: [1,2,3,1,1] => 0,3,4 这些是最小位置。 我尝试用两种方法来做到这一点,但这些都不起作用。 请有人帮
我需要找到整个矩阵的最小值,它是“坐标”。在像 这样的矩阵中 matrix = 8 7 6 5 4 3 2 1 最小值为 (2, 4) 处的 1。 最佳答案 这可以很简单地通过使用
给定一个正整数“l”和“r”。找到最小的数字“n”,使得 l r: cnt = 32 for i in range(l, r+1): s = bi
numpy.minimum 似乎不适用于复数: np.minimum(5+3*1j,4+30*1j) (4+30j) 我想保持最大幅度的值。它只比较实部。元素最小比较的任何其他功能? MATLAB m
鉴于数据库中的以下事实: foo(a, 3). foo(b, 2). foo(c, 4). foo(d, 3). foo(e, 2). foo(f, 6). foo(g, 3). foo(h, 2).
假设我们给出了给定图 G 的最小生成树 T(有 n 个顶点和 m 个边)和一条权重为 w 的新边 e = (u, v),我们将添加到 G 中。 I) 检查 T 是否仍然是 MST。II) 如果不是,请
我有一个名为“posts”的elasticsearch索引。 http://127.0.0.1:9200/posts/doc/_count返回{"count":240000,"_shards":{"t
我在 MySQL 中有一个表,名称如下 我有两件事要处理 1- 停用所有未使用的书籍 isActive = 1 - Active isActive = 0 - Inactive is_inuse =
我的站点位于 www.ethoma.com/wd/ . 如您所见,我已经使用自己的代码实现了主题和所有菜单。我想在我的网站上安装 WordPress,这样我就可以简单地在 WordPress 上输入我
当我在 bool 数组上使用 numpy 函数 minimum() 和 maximum() 时,结果类型打印为 numpy.int32。但是,与 numpy.int32 类型的比较失败(即使在转换之后
我在分布式系统中遇到分片移动问题。 【问题】 最初每个分区负责任意数量的分片。 (这个数字可以是任意的,因为系统支持将分片从一个分区移动到另一个分区) 然后一个新的分区来了,系统需要重新分片。目标是使
我有 3 个这样的观点: 我需要定义一个约束,以便在蓝色或芥末色垂直调整大小时,红色 View 将保持在任一上 View 的最小距离处,例如 或者 那么我怎样才能达到那个结果呢??? 最佳答案 建立从
题目地址:https://leetcode.com/problems/minimum-area-rectangle/description/ 题目描述 Given a set of points
题目地址:https://leetcode-cn.com/problems/path-with-minimum-effort/ 题目描述 你准备参加一场远足活动。给你一个二维 rows x col
题目地址:https://leetcode.com/problems/minimum-absolute-difference/ 题目描述 Given an array of distinct in
题目地址:https://leetcode.com/problems/minimum-height-trees/description/ 题目描述 Fora undirected graph wi
题目地址:https://leetcode.com/problems/minimum-time-difference/description/ 题目描述: Given a list of 24-h
题目地址: https://leetcode.com/problems/minimum-genetic-mutation/description/ 题目描述 Agene string can be
你们能帮我解决一些我被困的家庭作业问题吗? 完整二叉树中的局部最小值被定义为小于其所有邻居(邻居 = 父、左子、右子)的节点。 我需要在给定的完整二叉树中找到一个局部最小值,它的每个节点都有不同的数字
(defun *smaller* (x y) ( if (> x y) y x)) (defun *minimum* (lst) (do ((numbers lst (cdr
我是一名优秀的程序员,十分优秀!