No soy matemático, así que disculpen si esta pregunta resulta ser trivial. Necesito esto en el trabajo, pero no pude averiguar cómo resolver esto de manera eficiente, aunque parece que podría ser un problema muy común, y tal vez simple (sin embargo tengo un mal presentimiento sobre esto).
En cualquier caso, dada es una matriz de valores booleanos, es decir, ceros y unos.
Las operaciones permitidas son:
- Las filas se pueden intercambiar
- Las columnas se pueden intercambiar
El problema: utilizando sólo estas dos operaciones, ¿es posible convertir la matriz de entrada en una especie de matriz diagonal de bloques, con la salvedad de que los bloques no deben ser necesariamente matrices cuadradas, sino de tamaño restringido, es decir, el número de filas (o columnas) de cada bloque debe ser igual a un número determinado.
Por ejemplo:
Sea la matriz de entrada:
a b c d e f
--+------------
w | 1 0 0 0 1 0
x | 0 0 0 1 0 1
y | 1 0 1 0 0 0
z | 0 1 0 1 0 0
Y los bloques deben tener el tamaño (2,3), entonces una posible solución sería:
a e c d b f
--+------------
w | 1 1 0 0 0 0
y | 1 0 1 0 0 0
x | 0 0 0 1 0 1
z | 0 0 0 1 1 0
Aquí se han intercambiado las filas x e y las columnas b y e.
El problema también puede relajarse de forma que sólo se fije el número de columnas (o filas, pero no ambos) de las submatrices.
Lo necesito para encajar una matriz bastante grande pero escasa en una hoja de papel de anchura limitada, y la idea era reorganizarla como se ha descrito anteriormente y dividirla por la mitad. Sé que no siempre es posible, pero en los casos en que sí lo es, procedería a mostrar la matriz resultante así:
a e c
--+------
w | 1 1 0
y | 1 0 1
d b f
--+------
x | 1 0 1
z | 1 1 0
Así que mi pregunta es: ¿cómo se llama generalmente este problema? ¿Existe una formulación alternativa? Y, lo que es más importante, ¿existe un algoritmo (eficiente) para resolverlo (es decir, debe haber uno, no)? ¿Hay algún texto o algo en la web donde pueda buscarlo?
Muchas gracias por adelantado.
ACTUALIZACIÓN
He avanzado un poco en esto y -si no me he equivocado- resulta que se reduce a PARTICIÓN.
Básicamente, es relativamente fácil agrupar columnas en clases de equivalencia comprobando si hay alguna fila que tenga 1s en ambas columnas. Se me ocurrió este algoritmo:
- elige alguna celda con un 1
- golpear a través de él verticalmente y horizontalmente
- para cada celda que contenga un 1 que sea tachado, realice los pasos 2-3.
- eliminar la submatriz que contiene filas y columnas tachadas y repetir los pasos 1-4 hasta que no queden 1s
De este modo, obtenemos el conjunto de submatrices más pequeñas que luego deben combinarse para formar dos matrices de igual anchura (el objetivo era dividir la matriz de entrada por la mitad). En realidad, en el caso de que haya columnas todo-0, éstas pueden usarse para rellenar otras matrices hasta el tamaño requerido, pero esto sólo complica las cosas.
Además, en la segunda fase (combinar las submatrices), sólo es relevante la anchura de las submatrices, por lo que podemos considerar un conjunto múltiple de enteros positivos que representen la anchura de cada submatriz.
Exigir que este conjunto sea particionado en dos subconjuntos que sumen igual tamaño, bueno, eso es exactamente PARTICIONAR (sabía que había algo malo en este problema _).
Por cierto, dividir la matriz en más de dos trozos de tamaño más o menos igual se reduce a BIN PACKING.