Acabo de recibir una imagen ... La imagen de abajo de mi juego muestra algunos bloques oscuros, que han sido reconocidos como parte de una forma de "T". Como se puede ver, el código ha oscurecido los bloques con las manchas rojas y no ha visto las formas "T" con los contornos verdes.
Mi código recorre x / y, marca bloques como se usan, gira la forma, repite, cambia de color, repite.
He comenzado a tratar de arreglar esta comprobación con gran temor. La idea actual es:
- recorrer la cuadrícula y tomar nota de todas las ocurrencias de patrones (NO marcar bloques como se usan), y ponerlos en una matriz
- Vuelva a recorrer la cuadrícula, esta vez observando qué bloques están ocupados por qué patrones y, por lo tanto, cuáles están ocupados por múltiples patrones.
- recorriendo nuevamente la cuadrícula, esta vez observando qué patrones obstruyen qué patrones
Eso se siente bien ... ¿Qué hago ahora?
Yo creo que tendría que
- pruebe varias combinaciones de formas en conflicto, comenzando con aquellas que obstruyen la mayoría de los otros patrones primero. ¿Cómo me acerco a este?
- use el racional que dice que tengo 3 formas en conflicto que ocupan 8 bloques, y las formas son de 4 bloques cada una, por lo tanto, solo puedo tener un máximo de dos formas.
(También tengo la intención de incorporar otras formas, y probablemente habrá una ponderación de puntaje que deberá tenerse en cuenta al pasar por las formas en conflicto, pero eso puede ser otro día)
No creo que sea un problema de embalaje, pero no estoy seguro de qué buscar. Espero que tenga sentido, gracias por tu ayuda
EDITAR A pesar de la claridad de la pregunta, todo el mundo parece haber entendido, sí,
Quiero encontrar las formas máximas de "T" dentro de cada color
(porque si te diera puntos por dos y hubieras hecho tres, estarías un poco molesto)
Respuestas:
Déjame ver si acerté, los bloques marcados en rojo, eran azules y el algoritmo encontró una forma de T y los marcó en rojo, ¿es correcto? Su objetivo es encontrar tantas formas de T como sea posible con bloques del mismo color, correcto hasta ahora, espero. Actualmente los marca una vez que los encuentra y eso disminuye la utilidad del algoritmo (ya que podría faltar la solución óptima). Está planeando buscar todas las formas y luego elegir cuáles usar y cuáles no. ¿Estoy en lo correcto hasta ahora? Porque desea maximizar la cantidad de bloques que están contenidos dentro de las formas T cuando el algoritmo está listo.
Si estoy en lo correcto, la siguiente es la solución óptima para su situación en mi opinión.
Utilizaremos la programación lineal entera.
Creo que usé este en el pasado:
http://sourceforge.net/projects/lpsolve/
http://lpsolve.sourceforge.net/5.5/Java/README.html
(Puede hacer que funcione con muchos lenguajes, lo usé con PHP, Java y C)
Lo que haremos es registrar cada forma de T posible en el tablero y luego usar ILP para maximizar la cantidad de bloques que están cubiertos. ILP es exponencialmente complejo. Teniendo en cuenta el tamaño de su placa, eso no será un problema. He realizado preguntas mínimas / máximas mucho más complicadas en gráficos con ILP y solo tardó una fracción de segundo en completarse y hasta 30-90 segundos con cientos de vértices (en su caso, cae en la fracción de un segundo).
Lo que recomendaría hacer:
0 <= Bi <= 1
) Dado que los valores son enteros, eso deja 0 o 1.Bi + Bj <= 1
)Este es un conocimiento valioso, usé solucionadores lineales a menudo para proyectos de trabajo.
ILP es básicamente una forma de resolver problemas de selección en los que desea alcanzar un máximo o un mínimo para alguna función lineal.
Puede leer más aquí, el uso de la programación lineal de enteros y la programación lineal es lo mismo para el programador, solo que Integer es mucho más complejo para la computadora, lo que puede resultar en largos tiempos de ejecución. No en su caso, es muy simple y solo debería tomar menos de milisegundos en el peor de los casos.
Supongo que puedes leer más aquí:
http://en.wikipedia.org/wiki/Integer_linear_programming#Integer_unknowns
Esto lo explica bien:
http://fisher.osu.edu/~croxton_4/tutorial/
Básicamente es un solucionador de problemas de decisión, cómo tomar decisiones que maximicen el resultado que desea. Esto asume que la función que juzga el resultado es lineal, que en su caso actual específico es. La función que juzga el resultado en este caso, resume los bloques de todas las formas T que decidió oscurecer.
Matemáticamente, cómo establecer las variables: en nuestro caso actual Booleanos (oscurecí la forma de T con índice i o no) a los valores óptimos para maximizar el resultado que queremos: oscurecer tantos bloques como sea posible sin oscurecer las formas de T que se cruzan. Siempre que el resultado que desee se pueda calcular con una función lineal cuando tenga todas las variables establecidas, lo resolverá. En nuestro caso, verificamos qué formas de T hemos oscurecido y sumamos los bloques que cubren.
Sé que esto no es trivial, así que si eliges dar el salto, siéntete libre de comentar y daré más detalles.
fuente
Una vez que tenga una lista de todas las formas de T (posiblemente superpuestas) que ocurren en su cuadrícula, lo que le queda es un problema de empaquetado máximo .
En general, este es un problema NP-completo. Sin embargo, su cuadrícula es lo suficientemente pequeña (y generalmente se divide en subproblemas independientes aún más pequeños) que puede ser factible obtener soluciones exactas.
Anexo: Aquí hay un algoritmo de búsqueda de retroceso básico que podría ser útil:
Aquí,
{X, Y, Z}
denota el conjunto que contiene los elementosX
,Y
yZ
(con{}
ser el conjunto vacío), y|Q|
denota el tamaño del conjuntoQ
.En la función recursiva, el conjunto
A
contiene las formas disponibles para la solución restante,S
contiene las formas en el candidato de la solución actual yM
es la solución máxima hasta ahora (que es posible que desee almacenar como una variable global en lugar de devolverla de nuevo al cadena de llamadas). La optimización importante está en la línea marcada con// upper bound
, que poda las ramas del árbol de búsqueda que no pueden devolver una solución mejor queM
.(En realidad, dado que sabemos que cada forma de T contiene exactamente cuatro sitios, se podría obtener un límite superior mucho mejor reemplazando
|B|
con el número de sitios distintos cubiertos por las formas enB
, dividido por cuatro y redondeado hacia abajo (y de manera similar para|A|
el línea marcada con// shortcut
). Sin embargo, el algoritmo descrito anteriormente funciona para colecciones arbitrarias de formas).Una posible optimización adicional, que no he implementado anteriormente, sería verificar al comienzo de la función recursiva si se
A
divide en múltiples subconjuntos que son independientes, en el sentido de que no se superponen formas en diferentes subconjuntos, y si es así, aplique el algoritmo para cada uno de los subconjuntos por separado. (En cualquier caso, definitivamente querrá hacer esto al menos una vez en el nivel superior antes de llamar al algoritmo recursivo). Clasificar las formas de maneraA
apropiada antes de recorrerlas, por ejemplo, en orden creciente por número de formas superpuestas, también podría ayudar .fuente