transporte resueltos problemas online modelo metodo matriz introduccion hungaro ejemplos cuadrada asignacion algorithm matrix matching greedy hungarian-algorithm

algorithm - problemas - modelo de asignacion ejemplos resueltos



Algoritmo húngaro: ¿encontrar el número mínimo de líneas para cubrir ceros? (5)

Hay casos en que el código de Amir falla.

Considere el siguiente m1:

0 0 1 0 1 1 1 0 1

La mejor solución es dibujar líneas verticales en las dos primeras columnas.

El código de Amir daría los siguientes m2:

-2 -2 0 2 0 0 0 2 0

Y el resultado dibujaría las dos líneas verticales ASÍ COMO una línea en la primera fila.

Me parece que el problema es el caso de desempate:

return vertical > horizontal ? vertical : horizontal * -1;

Debido a la forma en que se escribe el código, el m1 muy similar NO fallará:

0 1 1 1 0 1 0 0 1

Donde la primera fila se mueve hacia abajo, porque la función de limpieza borrará los valores -2 de m2 antes de que se alcancen esas celdas. En el primer caso, los valores -2 se golpean primero, por lo que se dibuja una línea horizontal a través de la primera fila.

He estado trabajando un poco en esto, y esto es lo que tengo. En el caso de un empate, no establezca ningún valor y no trace una línea a través de esas celdas. Esto cubre el caso de la matriz que mencioné anteriormente, hemos terminado en este paso.

Claramente, hay situaciones en las que permanecerán los 0 que están descubiertos. A continuación hay otro ejemplo de una matriz que fallará en el método de Amir (m1):

0 0 1 1 1 0 1 0 1 1 0 1 1 0 1 1 1 0 0 1 1 1 1 1 1

La solución óptima es cuatro líneas, por ejemplo, las primeras cuatro columnas.

El método de Amir da m2:

3 -2 0 0 0 3 0 -2 0 0 3 0 0 -2 0 0 0 -2 -2 0 0 0 0 0 0

Lo cual dibujará líneas en las primeras cuatro filas y la primera columna (una solución incorrecta, dando 5 líneas). De nuevo, el caso del desempate es el problema. Resolvemos esto al no establecer un valor para los vínculos e iterar el procedimiento.

Si ignoramos los vínculos obtenemos un m2:

3 -2 0 0 0 3 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Esto lleva a cubrir solo la primera fila y la primera columna. Luego sacamos los 0 que están cubiertos para dar nuevo m1:

1 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 0 0 1 1 1 1 1 1

Luego seguimos repitiendo el procedimiento (ignorando las ataduras) hasta que lleguemos a una solución. Repita para un nuevo m2:

0 0 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0

Lo que lleva a dos líneas verticales a través de la segunda y tercera columnas. Todos los 0 ahora están cubiertos, y solo necesitan cuatro líneas (esta es una alternativa para alinear las primeras cuatro columnas). La matriz anterior solo necesita 2 iteraciones, y me imagino que la mayoría de estos casos necesitarán solo dos iteraciones, a menos que haya conjuntos de vínculos anidados dentro de conjuntos de relaciones. Traté de encontrar uno, pero se volvió difícil de manejar.

Tristemente, esto no es lo suficientemente bueno, porque habrá casos que permanecerán atados para siempre. Particularmente, en casos donde hay un ''conjunto disjunto de celdas atadas''. No estoy seguro de cómo describir esto, excepto para dibujar los siguientes dos ejemplos:

0 0 1 1 0 1 1 1 1 0 1 1 1 1 1 0

o

0 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 0 0 1 1 1 0 0

Las submatrices 3x3 superiores izquierdas en estos dos ejemplos son idénticas a mi ejemplo original, he añadido 1 o 2 filas / columnas a ese ejemplo en la parte inferior y derecha. Los únicos ceros recién agregados son donde se cruzan las nuevas filas y columnas. Describiendo por claridad.

Con el método iterativo que describí, estas matrices quedarán atrapadas en un ciclo infinito. Los ceros siempre permanecerán atados (recuento de col contra recuento de filas). En este punto, tiene sentido simplemente elegir arbitrariamente una dirección en el caso de un empate, al menos de lo que puedo imaginar.

El único problema al que me estoy enfrentando es configurar los criterios de parada para el ciclo. No puedo suponer que 2 iteraciones sean suficientes (o cualquier n), pero tampoco puedo descubrir cómo detectar si una matriz solo tiene bucles infinitos dentro. Todavía no estoy seguro de cómo describir estos conjuntos disjuntos atados computacionalmente.

Aquí está el código para hacer lo que se me ocurrió hasta ahora (en el script de MATLAB):

function [Lines, AllRows, AllCols] = FindMinLines(InMat) %The following code finds the minimum set of lines (rows and columns) %required to cover all of the true-valued cells in a matrix. If using for %the Hungarian problem where ''true-values'' are equal to zero, make the %necessary changes. This code is not complete, since it will be caught in %an infinite loop in the case of disjoint-tied-sets %If passing in a matrix where 0s are the cells of interest, uncomment the %next line %InMat = InMat == 0; %Assume square matrix Count = length(InMat); Lines = zeros(Count); %while there are any ''true'' values not covered by lines while any(any(~Lines & InMat)) %Calculate row-wise and col-wise totals of ''trues'' not-already-covered HorzCount = repmat(sum(~Lines & InMat, 2), 1, Count).*(~Lines & InMat); VertCount = repmat(sum(~Lines & InMat, 1), Count, 1).*(~Lines & InMat); %Calculate for each cell the difference between row-wise and col-wise %counts. I.e. row-oriented cells will have a negative number, col-oriented %cells will have a positive numbers, ties and ''non-trues'' will be 0. %Non-zero values indicate lines to be drawn where orientation is determined %by sign. DiffCounts = VertCount - HorzCount; %find the row and col indices of the lines HorzIdx = any(DiffCounts < 0, 2); VertIdx = any(DiffCounts > 0, 1); %Set the horizontal and vertical indices of the Lines matrix to true Lines(HorzIdx, :) = true; Lines(:, VertIdx) = true; end %compute index numbers to be returned. AllRows = [find(HorzIdx); find(DisjTiedRows)]; AllCols = find(VertIdx); end

Estoy tratando de implementar el algoritmo húngaro, pero estoy atascado en el paso 5 . Básicamente, dada una matriz de números n X n , ¿cómo puedo encontrar un número mínimo de líneas verticales + horizontales de manera que los ceros de la matriz estén cubiertos?

Antes de que alguien marque esta pregunta como un duplicado de this , la solución mencionada allí es incorrecta y alguien más también se encontró con el error en el código publicado allí .

No busco el código, sino el concepto por el que puedo dibujar estas líneas ...

EDITAR: Por favor, no publique el algoritmo codicioso simple (pero equivocado): Dada esta entrada:

(0, 1, 0, 1, 1) (1, 1, 0, 1, 1) (1, 0, 0, 0, 1) (1, 1, 0, 1, 1) (1, 0, 0, 1, 0)

Selecciono, columna 2 obviamente (0-indexado):

(0, 1, x, 1, 1) (1, 1, x, 1, 1) (1, 0, x, 0, 1) (1, 1, x, 1, 1) (1, 0, x, 1, 0)

Ahora puedo seleccionar la fila 2 o col 1, que tienen dos ceros "restantes". Si selecciono col2, termino con una solución incorrecta en esta ruta:

(0, x, x, 1, 1) (1, x, x, 1, 1) (1, x, x, 0, 1) (1, x, x, 1, 1) (1, x, x, 1, 0)

La solución correcta es usar 4 líneas:

(x, x, x, x, x) (1, 1, x, 1, 1) (x, x, x, x, x) (1, 1, x, 1, 1) (x, x, x, x, x)


La respuesta @CMPS falla en bastantes gráficos. Creo que he implementado una solución que resuelve el problema.

Seguí el artículo de Wikipedia sobre el algoritmo húngaro e hice una implementación que parece funcionar todo el tiempo. De Wikipedia, este es un método para dibujar el número mínimo de líneas:

Primero, asigne tantas tareas como sea posible. Marque todas las filas que no tienen asignaciones. Marque todas las columnas (sin marcar) con ceros en las filas marcadas recientemente. Marque todas las filas que tienen asignaciones en las columnas recién marcadas. Repita para todas las filas no asignadas.

Aquí está mi implementación de Ruby:

def draw_lines grid #copies the array marking_grid = grid.map { |a| a.dup } marked_rows = Array.new marked_cols = Array.new while there_is_zero(marking_grid) do marking_grid = grid.map { |a| a.dup } marked_cols.each do |col| cross_out(marking_grid,nil, col) end marked = assignment(grid, marking_grid) marked_rows = marked[0] marked_cols.concat(marked[1]).uniq! marking_grid = grid.map { |a| a.dup } marking_grid.length.times do |row| if !(marked_rows.include? row) then cross_out(marking_grid,row, nil) end end marked_cols.each do |col| cross_out(marking_grid,nil, col) end end lines = Array.new marked_cols.each do |index| lines.push(["column", index]) end grid.each_index do |index| if !(marked_rows.include? index) then lines.push(["row", index]) end end return lines end def there_is_zero grid grid.each_with_index do |row| row.each_with_index do |value| if value == 0 then return true end end end return false end def assignment grid, marking_grid marking_grid.each_index do |row_index| first_zero = marking_grid[row_index].index(0) #if there is no zero go to next row if first_zero.nil? then next else cross_out(marking_grid, row_index, first_zero) marking_grid[row_index][first_zero] = "*" end end return mark(grid, marking_grid) end def mark grid, marking_grid, marked_rows = Array.new, marked_cols = Array.new marking_grid.each_with_index do |row, row_index| selected_assignment = row.index("*") if selected_assignment.nil? then marked_rows.push(row_index) end end marked_rows.each do |index| grid[index].each_with_index do |cost, col_index| if cost == 0 then marked_cols.push(col_index) end end end marked_cols = marked_cols.uniq marked_cols.each do |col_index| marking_grid.each_with_index do |row, row_index| if row[col_index] == "*" then marked_rows.push(row_index) end end end return [marked_rows, marked_cols] end def cross_out(marking_grid, row, col) if col != nil then marking_grid.each_index do |i| marking_grid[i][col] = "X" end end if row != nil then marking_grid[row].map! {|i| "X"} end end grid = [ [0,0,1,0], [0,0,1,0], [0,1,1,1], [0,1,1,1], ] p draw_lines(grid)


Los algoritmos codiciosos pueden no funcionar en algunos casos.

En primer lugar, es posible reformular su problema de la siguiente manera: dado un gráfico bipartito, encuentre una cobertura de vértice mínima. En este problema, hay 2n nodos, n para filas yn para columnas. Hay un borde entre dos nodos si el elemento en la intersección de la columna y fila correspondiente es cero. La cubierta de vértice es un conjunto de nodos (filas y columnas) de modo que cada borde incide en algún nodo de ese conjunto (cada cero está cubierto por fila o columna).

Este es un problema bien conocido y se puede resolver en O (n ^ 3) encontrando una coincidencia máxima. Ver wikipedia para más detalles


Paso 5: El trazado de la línea en la matriz se evalúa diagonalmente con una evaluación máxima de la longitud de la matriz.

Basado en http://www.wikihow.com/Use-the-Hungarian-Algorithm con los pasos 1 a 8 solamente.

Ejecute el fragmento de código y vea los resultados en la consola

Salida de consola

horizontal line (row): {"0":0,"2":2,"4":4} vertical line (column): {"2":2} Step 5: Matrix 0 1 0 1 1 1 1 0 1 1 1 0 0 0 1 1 1 0 1 1 1 0 0 1 0 Smallest number in uncovered matrix: 1 Step 6: Matrix x x x x x 1 1 x 1 1 x x x x x 1 1 x 1 1 x x x x x

JSFiddle: http://jsfiddle.net/jjcosare/6Lpz5gt9/2/

// http://www.wikihow.com/Use-the-Hungarian-Algorithm var inputMatrix = [ [0, 1, 0, 1, 1], [1, 1, 0, 1, 1], [1, 0, 0, 0, 1], [1, 1, 0, 1, 1], [1, 0, 0, 1, 0] ]; //var inputMatrix = [ // [10, 19, 8, 15], // [10, 18, 7, 17], // [13, 16, 9, 14], // [12, 19, 8, 18], // [14, 17, 10, 19] // ]; var matrix = inputMatrix; var HungarianAlgorithm = {}; HungarianAlgorithm.step1 = function(stepNumber) { console.log("Step " + stepNumber + ": Matrix"); var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { var sb = ""; for (var j = 0; j < matrix[i].length; j++) { currentNumber = matrix[i][j]; sb += currentNumber + " "; } console.log(sb); } } HungarianAlgorithm.step2 = function() { var largestNumberInMatrix = getLargestNumberInMatrix(matrix); var rowLength = matrix.length; var columnLength = matrix[0].length; var dummyMatrixToAdd = 0; var isAddColumn = rowLength > columnLength; var isAddRow = columnLength > rowLength; if (isAddColumn) { dummyMatrixToAdd = rowLength - columnLength; for (var i = 0; i < rowLength; i++) { for (var j = columnLength; j < (columnLength + dummyMatrixToAdd); j++) { matrix[i][j] = largestNumberInMatrix; } } } else if (isAddRow) { dummyMatrixToAdd = columnLength - rowLength; for (var i = rowLength; i < (rowLength + dummyMatrixToAdd); i++) { matrix[i] = []; for (var j = 0; j < columnLength; j++) { matrix[i][j] = largestNumberInMatrix; } } } HungarianAlgorithm.step1(2); console.log("Largest number in matrix: " + largestNumberInMatrix); function getLargestNumberInMatrix(matrix) { var largestNumberInMatrix = 0; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { for (var j = 0; j < matrix[i].length; j++) { currentNumber = matrix[i][j]; largestNumberInMatrix = (largestNumberInMatrix > currentNumber) ? largestNumberInMatrix : currentNumber; } } return largestNumberInMatrix; } } HungarianAlgorithm.step3 = function() { var smallestNumberInRow = 0; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { smallestNumberInRow = getSmallestNumberInRow(matrix, i); console.log("Smallest number in row[" + i + "]: " + smallestNumberInRow); for (var j = 0; j < matrix[i].length; j++) { currentNumber = matrix[i][j]; matrix[i][j] = currentNumber - smallestNumberInRow; } } HungarianAlgorithm.step1(3); function getSmallestNumberInRow(matrix, rowIndex) { var smallestNumberInRow = matrix[rowIndex][0]; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { currentNumber = matrix[rowIndex][i]; smallestNumberInRow = (smallestNumberInRow < currentNumber) ? smallestNumberInRow : currentNumber; } return smallestNumberInRow; } } HungarianAlgorithm.step4 = function() { var smallestNumberInColumn = 0; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { smallestNumberInColumn = getSmallestNumberInColumn(matrix, i); console.log("Smallest number in column[" + i + "]: " + smallestNumberInColumn); for (var j = 0; j < matrix[i].length; j++) { currentNumber = matrix[j][i]; matrix[j][i] = currentNumber - smallestNumberInColumn; } } HungarianAlgorithm.step1(4); function getSmallestNumberInColumn(matrix, columnIndex) { var smallestNumberInColumn = matrix[0][columnIndex]; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { currentNumber = matrix[i][columnIndex]; smallestNumberInColumn = (smallestNumberInColumn < currentNumber) ? smallestNumberInColumn : currentNumber; } return smallestNumberInColumn; } } var rowLine = {}; var columnLine = {}; HungarianAlgorithm.step5 = function() { var zeroNumberCountRow = 0; var zeroNumberCountColumn = 0; rowLine = {}; columnLine = {}; for (var i = 0; i < matrix.length; i++) { zeroNumberCountRow = getZeroNumberCountInRow(matrix, i); zeroNumberCountColumn = getZeroNumberCountInColumn(matrix, i); if (zeroNumberCountRow > zeroNumberCountColumn) { rowLine[i] = i; if (zeroNumberCountColumn > 1) { columnLine[i] = i; } } else if (zeroNumberCountRow < zeroNumberCountColumn) { columnLine[i] = i; if (zeroNumberCountRow > 1) { rowLine[i] = i; } } else { if ((zeroNumberCountRow + zeroNumberCountColumn) > 2) { rowLine[i] = i; columnLine[i] = i; } } } var zeroCount = 0; for (var i in columnLine) { zeroCount = getZeroNumberCountInColumnLine(matrix, columnLine[i], rowLine); if (zeroCount == 0) { delete columnLine[i]; } } for (var i in rowLine) { zeroCount = getZeroNumberCountInRowLine(matrix, rowLine[i], columnLine); if (zeroCount == 0) { delete rowLine[i]; } } console.log("horizontal line (row): " + JSON.stringify(rowLine)); console.log("vertical line (column): " + JSON.stringify(columnLine)); HungarianAlgorithm.step1(5); //if ((Object.keys(rowLine).length + Object.keys(columnLine).length) == matrix.length) { // TODO: // HungarianAlgorithm.step9(); //} else { // HungarianAlgorithm.step6(); // HungarianAlgorithm.step7(); // HungarianAlgorithm.step8(); //} function getZeroNumberCountInColumnLine(matrix, columnIndex, rowLine) { var zeroNumberCount = 0; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { currentNumber = matrix[i][columnIndex]; if (currentNumber == 0 && !(rowLine[i] == i)) { zeroNumberCount++ } } return zeroNumberCount; } function getZeroNumberCountInRowLine(matrix, rowIndex, columnLine) { var zeroNumberCount = 0; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { currentNumber = matrix[rowIndex][i]; if (currentNumber == 0 && !(columnLine[i] == i)) { zeroNumberCount++ } } return zeroNumberCount; } function getZeroNumberCountInColumn(matrix, columnIndex) { var zeroNumberCount = 0; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { currentNumber = matrix[i][columnIndex]; if (currentNumber == 0) { zeroNumberCount++ } } return zeroNumberCount; } function getZeroNumberCountInRow(matrix, rowIndex) { var zeroNumberCount = 0; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { currentNumber = matrix[rowIndex][i]; if (currentNumber == 0) { zeroNumberCount++ } } return zeroNumberCount; } } HungarianAlgorithm.step6 = function() { var smallestNumberInUncoveredMatrix = getSmallestNumberInUncoveredMatrix(matrix, rowLine, columnLine); console.log("Smallest number in uncovered matrix: " + smallestNumberInUncoveredMatrix); var columnIndex = 0; for (var i in columnLine) { columnIndex = columnLine[i]; for (var i = 0; i < matrix.length; i++) { currentNumber = matrix[i][columnIndex]; //matrix[i][columnIndex] = currentNumber + smallestNumberInUncoveredMatrix; matrix[i][columnIndex] = "x"; } } var rowIndex = 0; for (var i in rowLine) { rowIndex = rowLine[i]; for (var i = 0; i < matrix.length; i++) { currentNumber = matrix[rowIndex][i]; //matrix[rowIndex][i] = currentNumber + smallestNumberInUncoveredMatrix; matrix[rowIndex][i] = "x"; } } HungarianAlgorithm.step1(6); function getSmallestNumberInUncoveredMatrix(matrix, rowLine, columnLine) { var smallestNumberInUncoveredMatrix = null;; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { if (rowLine[i]) { continue; } for (var j = 0; j < matrix[i].length; j++) { if (columnLine[j]) { continue; } currentNumber = matrix[i][j]; if (!smallestNumberInUncoveredMatrix) { smallestNumberInUncoveredMatrix = currentNumber; } smallestNumberInUncoveredMatrix = (smallestNumberInUncoveredMatrix < currentNumber) ? smallestNumberInUncoveredMatrix : currentNumber; } } return smallestNumberInUncoveredMatrix; } } HungarianAlgorithm.step7 = function() { var smallestNumberInMatrix = getSmallestNumberInMatrix(matrix); console.log("Smallest number in matrix: " + smallestNumberInMatrix); var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { for (var j = 0; j < matrix[i].length; j++) { currentNumber = matrix[j][i]; matrix[j][i] = currentNumber - smallestNumberInMatrix; } } HungarianAlgorithm.step1(7); function getSmallestNumberInMatrix(matrix) { var smallestNumberInMatrix = matrix[0][0]; var currentNumber = 0; for (var i = 0; i < matrix.length; i++) { for (var j = 0; j < matrix[i].length; j++) { currentNumber = matrix[i][j]; smallestNumberInMatrix = (smallestNumberInMatrix < currentNumber) ? smallestNumberInMatrix : currentNumber; } } return smallestNumberInMatrix; } } HungarianAlgorithm.step8 = function() { console.log("Step 8: Covering zeroes with Step 5 - 8 until Step 9 is reached"); HungarianAlgorithm.step5(); } HungarianAlgorithm.step9 = function(){ console.log("Step 9..."); } HungarianAlgorithm.step1(1); HungarianAlgorithm.step2(); HungarianAlgorithm.step3(); HungarianAlgorithm.step4(); HungarianAlgorithm.step5(); HungarianAlgorithm.step6();


Actualizar

Implementé el algoritmo húngaro en los mismos pasos proporcionados por el enlace que publicó: Algoritmo húngaro

Aquí están los archivos con comentarios: Github

Algoritmo (Mejorado codicioso) para el paso 3: (Este código es muy detallado y bueno para entender el concepto de elegir una línea para dibujar: horizontal versus vertical. Pero tenga en cuenta que este código de paso se mejora en mi código en Github )

  • Calcule el número máximo de ceros vertical contra horizontal para cada posición xy en la matriz de entrada y almacene el resultado en una matriz separada llamada m2 .
  • Mientras se calcula, si ceros horizontales> ceros verticales, el número calculado se convierte a negativo. (solo para distinguir qué dirección elegimos para un uso posterior)
  • Pasa por todos los elementos en la matriz de m2 . Si el valor es positivo, dibuja una línea vertical en la matriz m3 , si el valor es negativo, dibuja una línea horizontal en m3

Siga el siguiente ejemplo + código para comprender más el algoritmo:

Crear 3 matrices:

  • m1: First array, contiene los valores de entrada
  • m2: segundo conjunto, contiene maxZeroes (vertical, horizontal) en cada posición x, y
  • m3: Third array, contiene las líneas finales (0 índice descubierto, 1 índice cubierto)

Crea 2 funciones:

  • hvMax (m1, fila, col); devuelve el número máximo de ceros horizontales o verticales. (Número positivo significa número vertical, negativo significa horizontal)
  • clearNeighbours (m2, m3, fila, col); método vacío, borrará los vecinos horizontales si el valor en los índices de filas de columnas es negativo, o los vecinos verticales claros si es positivo. Además, establecerá la línea en la matriz m3, volteando el bit cero a 1.

Código

public class Hungarian { public static void main(String[] args) { // m1 input values int[][] m1 = { { 0, 1, 0, 1, 1 }, { 1, 1, 0, 1, 1 }, { 1, 0, 0, 0, 1 }, { 1, 1, 0, 1, 1 }, { 1, 0, 0, 1, 0 } }; // int[][] m1 = { {13,14,0,8}, // {40,0,12,40}, // {6,64,0,66}, // {0,1,90,0}}; // int[][] m1 = { {0,0,100}, // {50,100,0}, // {0,50,50}}; // m2 max(horizontal,vertical) values, with negative number for // horizontal, positive for vertical int[][] m2 = new int[m1.length][m1.length]; // m3 where the line are drawen int[][] m3 = new int[m1.length][m1.length]; // loop on zeroes from the input array, and sotre the max num of zeroes // in the m2 array for (int row = 0; row < m1.length; row++) { for (int col = 0; col < m1.length; col++) { if (m1[row][col] == 0) m2[row][col] = hvMax(m1, row, col); } } // print m1 array (Given input array) System.out.println("Given input array"); for (int row = 0; row < m1.length; row++) { for (int col = 0; col < m1.length; col++) { System.out.print(m1[row][col] + "/t"); } System.out.println(); } // print m2 array System.out .println("/nm2 array (max num of zeroes from horizontal vs vertical) (- for horizontal and + for vertical)"); for (int row = 0; row < m1.length; row++) { for (int col = 0; col < m1.length; col++) { System.out.print(m2[row][col] + "/t"); } System.out.println(); } // Loop on m2 elements, clear neighbours and draw the lines for (int row = 0; row < m1.length; row++) { for (int col = 0; col < m1.length; col++) { if (Math.abs(m2[row][col]) > 0) { clearNeighbours(m2, m3, row, col); } } } // prinit m3 array (Lines array) System.out.println("/nLines array"); for (int row = 0; row < m1.length; row++) { for (int col = 0; col < m1.length; col++) { System.out.print(m3[row][col] + "/t"); } System.out.println(); } } // max of vertical vs horizontal at index row col public static int hvMax(int[][] m1, int row, int col) { int vertical = 0; int horizontal = 0; // check horizontal for (int i = 0; i < m1.length; i++) { if (m1[row][i] == 0) horizontal++; } // check vertical for (int i = 0; i < m1.length; i++) { if (m1[i][col] == 0) vertical++; } // negative for horizontal, positive for vertical return vertical > horizontal ? vertical : horizontal * -1; } // clear the neighbors of the picked largest value, the sign will let the // app decide which direction to clear public static void clearNeighbours(int[][] m2, int[][] m3, int row, int col) { // if vertical if (m2[row][col] > 0) { for (int i = 0; i < m2.length; i++) { if (m2[i][col] > 0) m2[i][col] = 0; // clear neigbor m3[i][col] = 1; // draw line } } else { for (int i = 0; i < m2.length; i++) { if (m2[row][i] < 0) m2[row][i] = 0; // clear neigbor m3[row][i] = 1; // draw line } } m2[row][col] = 0; m3[row][col] = 1; } }

Salida

Given input array 0 1 0 1 1 1 1 0 1 1 1 0 0 0 1 1 1 0 1 1 1 0 0 1 0 m2 array (max num of zeroes from horizontal vs vertical) (- for horizontal and + for vertical) -2 0 5 0 0 0 0 5 0 0 0 -3 5 -3 0 0 0 5 0 0 0 -3 5 0 -3 Lines array 1 1 1 1 1 0 0 1 0 0 1 1 1 1 1 0 0 1 0 0 1 1 1 1 1

PD: El ejemplo que apuntó nunca ocurrirá porque, como puede ver en el primer ciclo, haga los cálculos tomando el máximo (horizontal, vertical) y guárdelos en m2. Entonces col1 no se seleccionará porque -3 significa dibujar una línea horizontal, y -3 se calculó tomando el máximo entre ceros horizontales y verticales. Entonces, en la primera iteración de los elementos, el programa ha comprobado cómo dibujar las líneas, en la segunda iteración, el programa dibuja las líneas.